4

Я занимаюсь универсальным приложением, используя классы размера, и я пытаюсь использовать SplitView с помощью TabBarController в режиме Master/Primary. Перед добавлением splitView все работает нормально, но теперь приложение сработает (причина зависит от иерархии просмотров).IOS8 SplitVC + TabBarController + NavigationController

Итак, я попробовал такую ​​же раскадровку, начиная с шаблона Apple SplitView и добавляя TabBarController на свой основной/основной вид ... той же проблемы.

Иерархия - Встроенный мастер NavigationController в TabBarController: SplitVC (Master)> TabBarController> NavigationController> TableView SplitVC (Detail)> NavigationController> Просмотр

Добавлен этот код в AppDelegate.m (как показано здесь stackoverflow questions ios8-tabbarcontroller..., чтобы предотвратить DetailView представляется модально):

- (BOOL)splitViewController:(UISplitViewController *)splitViewController showDetailViewController:(UIViewController *)vc sender:(id)sender { 
     NSLog(@"UISplitViewController collapsed: %d", splitViewController.collapsed); 

    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) 
    { 
     if (splitViewController.collapsed) { 
      UITabBarController *master = (UITabBarController *) splitViewController.viewControllers[0]; 
      UINavigationController *masterNavigationController = (UINavigationController *)master.selectedViewController; 
      UINavigationController *destinationNavigationController = (UINavigationController *)vc; 

      // push detail view on the navigation controller 
      [masterNavigationController pushViewController:[destinationNavigationController.viewControllers lastObject] animated:YES]; 

      return YES; 
     } 
    } 

    return NO; 
} 

Он отлично работает ... если вы не имитировать в iPhone6 ​​Plus, в этом случае, после запуска в портретном и выбрать строку, если повернуть в ландшафтном я вижу детали вид на s первичный И вторичный вид.

Без добавления этого кода в портретной ориентации с iPhones подробный вид представлен в формате и, конечно, без кнопок навигации.

EDIT

После различных попыток и с каким-то внешним помогает я сделал несколько шагов вперед решение.

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

Правильное решение проблемы заключается в подкласс TabBarController и сделать его поддерживают некоторые методы:

@implementation MyTabBarController 

- (void)showViewController:(UIViewController *)vc sender:(id)sender 
{ 
    if ([self.selectedViewController isKindOfClass:UINavigationController.class]) 
     [self.selectedViewController showViewController:vc sender:sender]; 
    else 
     [super showViewController:vc sender:sender]; 
} 

- (UIViewController*)separateSecondaryViewControllerForSplitViewController:(UISplitViewController *)splitViewController 
{ 
    return [self.selectedViewController separateSecondaryViewControllerForSplitViewController:splitViewController]; 
} 

- (void)collapseSecondaryViewController:(UIViewController *)secondaryViewController forSplitViewController:(UISplitViewController *)splitViewController 
{ 
    [self.selectedViewController collapseSecondaryViewController:secondaryViewController forSplitViewController:splitViewController]; 
} 

сейчас У меня проблема с стекю viewControllers: с iPhone6Plus (единственный, поддерживающий как горизонтальный регулярный, так и компактный) приложение сбой, если в ландшафте вы меняете вкладку, не выбирая строку (так что detailView остается той, что была на предыдущей вкладке) а затем повернуть в портрет.

Я знаю, что мне нужно реализовать методы разделения и сглаживания, управляющие стеками представлений, но я не могу понять, как это сделать. Может кто-нибудь помочь в этом?

Длинная версия (поведение SplitViewController)

Обычно контроллер вид расщепляется и навигационный контроллер работы вместе, чтобы гарантировать, что вызов -showDetailViewController: отправитель: из контроллера вида, который содержится в пределах вида разделения контроллер выводит на новый контроллер подробного представления на стек навигационной системы (когда он находится в горизонтально компактной среде). В это сделать, UISplitViewController переопределяет -showDetailViewController: отправитель: и, если он по горизонтали компактен, вызывает его -showViewController главного контроллера представления: метод-отправитель:. UINavigationController переопределяет -showViewController: отправитель: и подталкивает контроллер входящего представления в стек навигационной панели.

UITabBarController однако не переопределяет -showViewController: отправитель: и поэтому он наследует реализацию по умолчанию, которая представляет контроллер входящего представления по модулю. Чтобы обойти это, мне нужно подклассифицировать UITabBarController и переопределить -showViewController: отправитель: переслать выбранный контрольный контроллер контроллера панели вкладок, если выбранный контроллерView - это контроллер навигации .

Кроме того, когда режим просмотра контроллер переходит из компактного до горизонтального размера к классу обычного горизонтального размера класса, вид контроллера сплит сначала отправляет -splitViewController: separateSecondaryViewControllerFromPrimaryViewController: сообщение для его делегата. Делегат может реализовать этот метод, и обрабатывает само разделение, возвращая контроллер подробного представления. Если делегат не реализует этот метод или если реализация возвращает nil, контроллер разделенного представления отправляет сообщение -separateSecondaryViewControllerForSplitViewController: в его основной контроллер представления. Контроллер первичного представления должен реализовать метод для обработки разделения. UINavigationController делает реализовать -separateSecondaryViewControllerForSplitViewController :. Это реализация выталкивает контроллер верхнего вида с панели навигации и возвращает ее. Поскольку я использую контроллер панели вкладок в качестве главного контроллера представления , я должен реализовать -separateSecondaryViewControllerForSplitViewController: и самостоятельно обрабатывать разделение.

Также мне нужно реализовать свою собственную коллапсирующую логику. Когда сплит-просмотр контроллер переходит от обычного к горизонтальному размерному классу в класс компактного горизонтального размера , контроллер разделенного представления сначала отправляет сообщение -splitViewController: collapseSecondaryViewController: onPrimaryViewController: своему делегату. Делегат может реализовать этот метод, и обрабатывает сам коллапс. Если делегат не реализует этот метод , контроллер разделенного представления отправляет сообщение -collapseSecondaryViewController: forSplitViewController: в свой основной контроллер представления. Контроллер первичного представления должен реализовать этот метод для обработки разделения.

UINavigationController реализует -collapseSecondaryViewController: forSplitViewController :. Это реализация нажимает дополнительный контроллер представления на стек навигационной панели . Поскольку я использую контроллер панели вкладок в качестве главного контроллера представлений , я должен реализовать -collapseSecondaryViewController: forSplitViewController: и обрабатывать коллапс самостоятельно.

ответ

0

Итак, я нашел то, что работает, даже если это не стандартное поведение:

- (void)collapseSecondaryViewController:(UIViewController *)secondaryViewController forSplitViewController:(UISplitViewController *)splitViewController 
{ 
    [self.selectedViewController.navigationController collapseSecondaryViewController:secondaryViewController forSplitViewController:splitViewController]; 
} 

Это эквивалентно вернуться всегда YES в splitViewController:collapseSecondaryViewController:ontoPrimaryViewController: метод делегирования. Как и вы, вы всегда отказываетесь от вторичного контроллера. Надеюсь, это может помочь кому-то.

0

Попробуйте этот фрагмент и сообщите нам свои результаты.Этот фрагмент кода получить с веб-сайта за пределами StackOverflow (Craig Marvelley)

#pragma mark - Split view 
// Update secondaryview with the right screen 
- (UIViewController *)splitViewController:(UISplitViewController *)splitViewController separateSecondaryViewControllerFromPrimaryViewController:(UIViewController *)primaryViewController { 
int tryIt = 0; 

if ((IS_IPHONE_6_PLUS) && (isLandscape)) { 
    if ([primaryViewController isKindOfClass:[UINavigationController class]]) { 
     for (UIViewController *controller in [(UINavigationController *)primaryViewController viewControllers]) { 
      tryIt = tryIt + 1; 
      if ([controller isKindOfClass:[UINavigationController class]] && ([[(UINavigationController *)controller visibleViewController] isKindOfClass:[yourPosibleScreen01 class]] || [[(UINavigationController *)controller visibleViewController] isKindOfClass:[yourPosibleScreen02 class]])) { 
       return controller; 
      } 
      // Sublevel where yo are to select the right screen. You must try with a number depends of how many internal hierarchy. But I believe you need number 2 but try it :) 
      if (tryIt > 2) { 
       return controller; 
      } 
     } 
    } 
    // Update detail screen 
    UIViewController *toViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"YourScreenToShow"]; 
    return toViewController; 
} 
return nil; 
} 


- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController { 

    return NO; 
} 
#pragma mark - Split view 
+0

Не работает, такой же проблема. Вы пробовали? Это работает для вас? – Zag

+0

Здравствуйте @Zag, извините, но я забыл счетчик уровней. Я не знаю почему, но иногда (после смены портрета на земли или наоборот) у нас есть 3 экрана, а не только 2, я полагаю, это всего лишь порядок внутреннего действия на экран для обуви. Код выше работает для меня. – Beto

+0

Привет @Beto, AFAIK изменение иерархии SplitViewController в зависимости от сложенного или разделенного режима. См. [Эта статья] (http://averagejake.com/post/104146203887/uisplitviewcontroller-adaptability-part-1). Я попробую ваше решение. Благодарю. – Zag

Смежные вопросы