Swift: how to detect if UISplitViewController is currently showing 1 or 2 controllers?
Asked Answered
P

3

10

How can I detect if the UISplitViewController is currently just showing 1 view controller or it's in dual-pane with 2 views controllers shown side-by-side?

Phylis answered 15/11, 2015 at 14:56 Comment(0)
A
13

The split view controller reflects the actual display mode in the displayMode property:

AllVisible: The primary and secondary UIViewControllers are displayed side-by-side.

PrimaryHidden: The primary UISplitViewController is hidden.

PrimaryOverlay: The primary UISplitViewController overlays the secondary, which is partially visible.

When the isCollapsed property is true, the value of displayMode property is ignored. A collapsed split view interface contains only one view controller so the display mode is superfluous.


Resume: To find out the detailed situation on screen use isCollapsed property and (if isCollapsed = false) displayMode property.

Antecede answered 25/9, 2016 at 6:11 Comment(1)
Careful these are not set in viewDidLoad nor viewWillAppear. If you need to do something on load you need to check in viewDidAppear.Sparid
M
4

Here is a simple case:

You are on the MasterViewController and you select a cell. Now, depending if the UISplitViewController is collapsed or not you want to either perform a segue (circled in red)

Segue to perform

to the DetailViewController (collapsed) or update the DetailViewController (not collapsed).

In your "didSelectRowAtIndexPath" method on your MasterViewController get a reference to the UISplitViewController and choose what to do like this:

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        //Reference to Split View
        guard let splitView = self.splitViewController else {
            return
        }
        //Check the collapsed property
        if splitView.collapsed {
            self.performSegueWithIdentifier("segueToDetail", sender: self)
        }else {
            //Get reference to your details navigation controller
            guard let detailViewNavigationController  = self.splitViewController?.viewControllers[1] as? UINavigationController else {
                return
            }
            //Get a reference to your custom detail view controller
            guard let detailController = detailViewNavigationController.viewControllers[0] as? MyCustomViewController else {
                return
            }
            //Call your custom function to update the detail view controller
            detailController.updateSomething()
        }
     }

If you don't want to use the "collapsed" property of the UISplitViewController you can check the number of view controllers property like this.

        if splitView.viewControllers.count == 1 {
            self.performSegueWithIdentifier("segueToDetail", sender: self)
        }else splitView.viewControllers.count == 2 {
            guard let detailViewNavigationController  = self.splitViewController?.viewControllers[1] as? UINavigationController else {
                return
            }

            guard let detailController = detailViewNavigationController.viewControllers[0] as? MyCustomViewController else {
                return
            }

            detailController.updateSomething()
        }

Another option is to set up delegation from your master view controller to your detail view controller. This will work well if you don't want to have to reach up the view controller chain like this example does. Here is a tutorial on this method. Note the "Hooking Up The Master With the Detail" section.

Just a note: I tested switching on the UISplitViewControllers "displayMode" property. This property did not give me enough info to figure out what to do. The reason is that the property is set to .AllVisible when you are in the horizontal compact mode and the horizontal expanded mode.

Last, before I go. I like the way I do it because lots of times you know you are going to need a UISplitViewController so you create a project from the template. You will notice the template comes with the segue set up. This template is great for phones but doesn't cut it for iPads and iPhone6+'s. If you drag and drop a UISplitViewController onto a story board after project creation you will notice the detail view is neither imbedded in a UINavigationController nor is there a segue from the master to the detail. Just more to set up I guess!

Misdemean answered 24/7, 2016 at 1:13 Comment(0)
S
0

There is a property of UISplitViewController named 'collapsed'.

Swaim answered 15/11, 2015 at 15:5 Comment(4)
on iPhones (where only 1 screen is shown), collapsed is falsePhylis
on iPhone at first launch 'collapsed' is always false and then it collapsed some time later.Swaim
Yea kind of headache :(Swaim
I also saw what @JasonNam mentioned, that collapsed is always false on launch then collapsed some time later. To get around this, I checked traitCollection.horizontalSizeClass to see if it's .unspecified. If it is, then collapsed is unreliable.Teaching

© 2022 - 2024 — McMap. All rights reserved.