Adaptive show detail segue преобразуется в модальный, а не нажимает на iPhone, когда главный контроллер просмотра является UITabBarController

В XCode 6, если вы создаете новый проект на основе шаблона приложения Master-Detail, вы получаете универсальную раскадровку, которая должна быть хорошей для всех устройств.

При выборе ячейки в главном представлении подробный вид обновляется через адаптивный "show detail" segue. На iPhone 4, 5, 6 или 6+ в портрете этот отступ примет форму толчка, как ожидалось. На iPad или iPhone 6+ в ландшафте это приведет к обновлению подробного представления, как ожидалось.

Теперь, если вы вставляете UITabBarController в качестве контроллера главного представления, который имеет вкладку к исходному контроллеру главного представления, адаптивный сегмент, который возникает при выборе ячейки в главном представлении, не ведет себя так, как ожидалось на iPhone. Вместо того, чтобы перейти к push-переходу, теперь вы получаете модальный переход. Как я могу это исправить? Кажется странным, что это не поддерживается по умолчанию.

Я нашел следующее сообщение полезным: iOS8 TabbarController внутри мастера UISplitviewController Но при использовании предложенного метода я не получаю правильное поведение на iPhone 6 Plus, когда я поворачиваюсь к пейзажу после нажатия на портрет. Содержимое подробного представления появляется в главном представлении, что неудивительно, поскольку это то, что предлагает предлагаемое решение.

Спасибо!

Ответы

Ответ 1

Повторное просмотр видео с WWDC14 Я думаю, что нашел лучший ответ.

  • Использовать пользовательский UISplitViewController (подкласс)
  • Переопределить операцию showDetailViewController
  • Используйте traitCollection для определения класса UISplitViewController
  • Если горизонтальный класс является компактным, попросите диспетчер навигации вызвать showViewController

Вот код пользовательского UISplitViewController:

import UIKit

class CustomSplitViewController: UISplitViewController {

    override func showDetailViewController(vc: UIViewController!, sender: AnyObject!) {

        if (self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.Compact) {
            if let tabBarController = self.viewControllers[0] as? UITabBarController {
                if let navigationController = tabBarController.selectedViewController as? UINavigationController {
                    navigationController.showViewController(vc, sender: sender)
                    return
                }
            }
        }

        super.showDetailViewController(vc, sender: sender)
    }
}

Не забудьте установить пользовательский класс в раскадровку.

Протестировано в симуляторе iPhone 6, iPhone 6+ и iPad Air и работает как ожидалось.

Ответ 2

К сожалению, выбранный ответ не сработал у меня. Однако в конечном итоге мне удалось решить проблему:

  • Подкласс UISplitViewController и установите новый класс в Interface Builder.
  • Сопоставьте новый класс с UISplitViewControllerDelegate:

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.delegate = self
    }
    
  • Выполните следующие два метода:

    func splitViewController(_ splitViewController: UISplitViewController,
                             collapseSecondary secondaryViewController:UIViewController,
                             onto primaryViewController:UIViewController) -> Bool {
        return true
    }
    
    func splitViewController(_ splitViewController: UISplitViewController,
                             showDetail vc: UIViewController,
                             sender: Any?) -> Bool {
    
        if splitViewController.isCollapsed {
            guard let tabBarController = splitViewController.viewControllers.first as? UITabBarController else { return false }
            guard let selectedNavigationViewController = tabBarController.selectedViewController as? UINavigationController else { return false }
    
            // Push view controller
            var detailViewController = vc
            if let navController = vc as? UINavigationController, let topViewController = navController.topViewController {
                detailViewController = topViewController
            }
            selectedNavigationViewController.pushViewController(detailViewController, animated: true)
            return true
        }
        return false
    }
    

Ответ 3

Когда docs находится в свернутом состоянии, он обрабатывает showDetail, вызывая show на главном контроллере представления, который в вашем случае является контроллером вкладок. Подкласс вашего контроллера вкладок, переопределить show и call show на дочернем контроллере навигации.