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.

  1. Use a custom UISplitViewController (subclass)
  2. Override the showDetailViewController operation
  3. Use the traitCollection to determine the class of the UISplitViewController
  4. 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:

  1. Subclass UISplitViewController and set the new class in Interface Builder.
  2. Make the new class conform to UISplitViewControllerDelegate:

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.delegate = self
    }
    
  3. 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
    }
    

Tags:

Ios

Iphone