Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update app UI after split view controller display mode changes?

I need to be able to update my app's UI when the split view controller's display mode changes. Specifically, if it goes from an expanded interface to a collapsed interface, I need to do something, and also if it goes from collapsed to expanded.

I am currently handling this via traitCollectionDidChange and while this seems to be working good for two of my split view controllers, the third one isn't working. It seems this method is getting called too early, so that when I check the displayMode to see if it's UISplitViewcontrollerDisplayModeAllVisible, the split view hasn't yet updated to the new display mode. So it ends up removing buttons that I want to actually want to add, or adds them when I wanted to remove them. If I delay checking that display mode just 0.1 second later, the displayMode value correctly represents what it will be when rotation completes and the appropriate action is taken.

My question is, is there a better method to use to update my app's UI, perhaps is there a way to know when the displayMode changes? I don't want to risk it calling it too early, but I also don't want to wait until rotation completes to update the UI. Delaying the check is a very fragile solution that may easily result in unexpected behavior, sometimes it might not work.

like image 338
Jordan H Avatar asked Dec 10 '25 09:12

Jordan H


2 Answers

A more robust solution would be to use primaryViewControllerForCollapsingSplitViewController: and primaryViewControllerForExpandingSplitViewController: in the UISplitViewControllerDelegate.

From the documentation it says

If you do not implement this method, or if your implementation returns nil, the split view controller chooses its primary view controller as the one to display.

So implement these methods to track collapse and expand, then return nil and you'll still get the default behavior.

like image 127
DBD Avatar answered Dec 12 '25 21:12

DBD


had a similar issue and discovered this delegate method on UISplitViewControllerDelegate

func targetDisplayModeForActionInSplitViewController(svc: UISplitViewController) -> UISplitViewControllerDisplayMode

Only problem is that it when you ask svc.displayMode, it tells you what mode its coming from and not where its going. However, its enough info to be able to prevent the UISplitViewController from going into a particular state.

    func targetDisplayModeForActionInSplitViewController(svc: UISplitViewController) -> UISplitViewControllerDisplayMode {
    switch svc.displayMode {
    case    .PrimaryOverlay :
        return .AllVisible
    case .AllVisible :
        return .PrimaryHidden
    case .PrimaryHidden :
        return .AllVisible
    case .Automatic :
        return .AllVisible
    default:
        return .AllVisible
    }
}

The other delegate method that I was able to use to know when my UISplitViewController display mode was changing is

func splitViewController(svc: UISplitViewController, willChangeToDisplayMode displayMode: UISplitViewControllerDisplayMode)

Then you can change the view accordingly if you handle the states that matter to you

 func splitViewController(svc: UISplitViewController, willChangeToDisplayMode displayMode: UISplitViewControllerDisplayMode) {
    println("will change to display mode \(displayMode.rawValue)")


    if (displayMode == UISplitViewControllerDisplayMode.AllVisible) {
           //do something because EVERYTHING is visible      
    } else if (displayMode == UISplitViewControllerDisplayMode.PrimaryHidden) {
       //something else because the primary is GONE
    } else if (self.splitViewController?.displayMode == UISplitViewControllerDisplayMode.PrimaryOverlay){
       //handle primary overlay change
    }
}
like image 28
bolnad Avatar answered Dec 12 '25 21:12

bolnad