Adaptive show detail segue transformed to modal instead of push on iPhone when master view controller is a UITabBarController
Re-watching videos from WWDC14 I think I've found a better answer.
- Use a custom UISplitViewController (subclass)
- Override the showDetailViewController operation
- Use the traitCollection to determine the class of the UISplitViewController
- If the horizontal class is Compact, get the navigationController to call showViewController
Here is the the code of the custom 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)
}
}
Do not forget to the set the custom class in the storyboard.
Tested in the simulator of iPhone 6, iPhone 6+ and iPad Air and worked as expected.
Unfortunately, the selected answer didn't work for me. However, I did eventually manage to solve the problem:
- Subclass
UISplitViewController
and set the new class in Interface Builder. Make the new class conform to
UISplitViewControllerDelegate
:required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.delegate = self }
Implement these two methods:
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 }