0

У меня возникла проблема с поддержкой восстановления состояния в iPhone 6+.Состояние восстановления iPhone 6+ с панелью вкладок в режиме главного разделения

Вот моя иерархия: enter image description here

Проблема заключается в том, когда состояние восстановление происходит в книжной ориентации, а затем, на более позднем этапе, состояние попытка декодирования производится в альбомной ориентации.

Пояснение: В портретном режиме в качестве основного вида имеется только TabBar (фактически, детальный вид не существует), поэтому он вставляется в контроллер навигации TabBar.

Затем, когда приложение попытается выполнить восстановление состояния для пейзажа, мое представление деталей будет перенесено на главный навигационный контроллер (когда он будет подробно).

Из-за пользовательской иерархии я применил соответствующие методы UISplitViewControllerDelegate, и они отлично работают. методы UISplitViewControllerDelegate также убедитесь, что состояние восстановительных работ в следующих случаях:

Landscape -> Landscape 
Landscape -> Portrait 
Portrait -> Portrait 

что не работает это: Портрет -> Пейзаж, потому что, как я уже говорил, метод делегата не дозвонился, когда в не разрушился состояние так иерархия представления не знает, как разделить детали из главного представления и внедрить это в подробный контроллер навигации.

ответ

0

До сих пор я решил это так: в viewWillAppear все контроллеры детали вырезаны из навигационных контроллеров панели вкладок. При сохранении состояния сохраняется ориентация устройства и SplitViewController.viewControllers (для меня он не будет автоматически сохранять их, как на iOS7).

- (void) encodeRestorableStateWithCoder:(NSCoder*)coder 
{ 
    [super encodeRestorableStateWithCoder:coder]; 
    [coder encodeObject:self.viewControllers forKey:@"viewControllers"]; 
    [coder encodeInteger:[UIApplication sharedApplication].statusBarOrientation forKey:@"orientation"]; 
} 

- (void) decodeRestorableStateWithCoder:(NSCoder*)coder 
{ 
    [super decodeRestorableStateWithCoder:coder]; 
    NSArray* viewControllers = [coder decodeObjectForKey:@"viewControllers"]; 
    if (viewControllers.count > 0) 
    { 
     self.viewControllers = viewControllers; 
    } 
    restoredOrientation = (UIInterfaceOrientation) [coder decodeIntegerForKey:@"orientation"]; 
} 

А вот viewWillAppear реализация:

- (void) viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 

    // iPhone6+: if state restoration happened while in portrait orientation and app is launched while in landscape, 
    // then all detail views should be cut from master view and split details view is set appropriately 
    if (firstLoad && 
      [UIScreen mainScreen].scale > 2.9 && // assure it's iPhone 6+ 
      UIInterfaceOrientationIsPortrait(restoredOrientation) && 
      UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication.statusBarOrientation)) 
    { 
     UITabBarController* tbc = self.viewControllers[0]; 
     NSArray* detachedControllers = [tbc cutControllersFrom:DocumentViewController.class]; 
     if (detachedControllers.count > 0) 
     { 
      UINavigationController* documentNavigation = [self.storyboard 
        instantiateViewControllerWithIdentifier:@"NavigationController"]; 
      documentNavigation.viewControllers = detachedControllers; 
      self.viewControllers = @[ self.viewControllers[0], documentNavigation ]; 
     } 
     else // place some default no-selection controller in detail 
     { 
      UINavigationController* noSelectionNavigation = [self.storyboard 
        instantiateViewControllerWithIdentifier:@"NoSelectionSID"]; 
      self.viewControllers = @[ self.viewControllers.firstObject, noSelectionNavigation ]; 
     } 
    } 
    firstLoad = NO; 
} 

где метод cutControllersFrom категория на UITabBarController:

- (NSArray*) cutControllersFrom:(Class)controllerClass 
{ 
    NSArray* ret; 
    for (UIViewController* vc in self.viewControllers) 
    { 
     if (![vc isKindOfClass:UINavigationController.class]) 
     { 
      continue; 
     } 

     UINavigationController* nc = (UINavigationController*) vc; 
     NSArray* removed = [nc cutFrom:controllerClass]; 
     if (vc == self.selectedViewController) 
     { 
      ret = removed; 
     } 
    } 

    return ret; 
} 

который вызывает cutFrom: метод, который является категорией на UINavigationController:

- (NSArray*) cutFrom:(Class)controllerClass 
{ 
    NSMutableArray* toRemove = [NSMutableArray array]; 
    BOOL startRemoving = NO; 
    UIViewController* endingViewController; 

    for (NSUInteger i = 0; i < self.viewControllers.count; i++) 
    { 
     UIViewController* vc = self.viewControllers[i]; 
     if ([vc isKindOfClass:controllerClass]) 
     { 
      startRemoving = YES; 
      endingViewController = self.viewControllers[i - 1]; 
     } 

     if (startRemoving) 
     { 
      [toRemove addObject:vc]; 
     } 
    } 
    if (endingViewController) 
    { 
     [self popToViewController:endingViewController animated:NO]; 
    } 

    return toRemove; 
} 
+0

Кажется, у вас мало выбора и хорошо сделано, чтобы понять все это. Если бы вы воспользовались сменой подхода, одним из вариантов было бы не использовать панели вкладок и перейти к боковой панели. Я делаю это в своем текущем приложении, где боковое меню позволяет мне переключаться между несколькими контроллерами с раздельным представлением. Хорошо, что каждый отдельный вид разделен отдельно и имеет навигационные контроллеры для мастера и детали, поэтому проще. Таким образом, ваша панель вкладок может стать меню боковой панели, которое позволит вам переключаться между четырьмя контроллерами с раздельным представлением: по одному для каждого контроллера. Просто мысль. –

+0

Ах да, боковое меню - идея neet. Пока что я должен придерживаться TabBar, но для будущей ссылки было бы очень хорошо иметь это в виду. – mixtly87

0

Не уверен, что я полностью понимаю вашу проблему, как происходит с портретной на ландшафтную на iPhone 6+ должны идти из сложенного состояния в разделенном состоянии, поэтому следует назвать этот делегат:

- (UIViewController *)splitViewController:(UISplitViewController *)splitViewController separateSecondaryViewControllerFromPrimaryViewController:(UIViewController *)primaryViewController

Однако вы, кажется, подразумевают, что это не называется, а в портрете оно находится в состоянии без сглаживания?

На контроллерах с раздельным просмотром, которые я использую, я нашел, что лучше всего позволить контроллеру разобраться в себе. Если вы используете showDetail segues для подробного представления, он должен обрабатывать split для вас. Убедитесь, что вы используете showDetail segues, чтобы вывести DetailController из Controller1-> 4, а не показывать segues?

Следовательно, предполагая, что вы используете правильные ответы на детали, просто верните nil в делегатах, чтобы позволить контроллеру разделенного вида сортировать себя?

+0

SplitViewController может сортировать информацию, если master является UINavigationController, но в моем случае это UITabBarController, у которого есть собственные UINavigationControllers, и это то, что UISplitViewController не знает, как разобраться, поэтому мне пришлось делать это вручную, применяя методы UISplitViewControllerDelegate. – mixtly87

+0

Хорошо. Возможно, вам нужно реализовать '- splitViewController: showDetailViewController: sender:' в вашем контроллере разделенного вида, чтобы вы могли разместить деталь в правильном месте? –

+0

Я уже применяю этот метод, но тот не вызван для восстановления состояния. – mixtly87