Trials with UISplitViewController (iOS 8 and later)

I'm currently writing an updated version of a popular app that will take advantage of split views on iPhone and iPad.

With iOS 8, Apple made considerable changes to UISplitViewController (details can be found at developer.apple.com). It now respects size classes and presents master and detail view controllers at the same time on iPhone 6/6S plus.

I ran into an issue where, on the iPhone 6 Plus, if you ran the app in portrait, it would open to the detail view. This isn't want I wanted (and don't think this is what other developers expect to be default behaviour). When I began implementing the new UISplitViewController delegate methods, I put them into the app delegate until I had a better place to put them and thought nothing of it.

The problem lies in placing view controller delegate methods in an app delegate - they weren't called until the app's UI was visible and responsive.

The solution (sort of) is to place UISplitViewController's delegate methods within a subclass of UISplitViewController. It's ugly, it breaks Cocoa conventions - I hate it. It's also the only thing that seems to work. This cannot be Apple's intended implementation, can it?

For those who want a more detailed explanation, the method below wasn't being called until after UIKit had presented its stack.

- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {

 if ([secondaryViewController isKindOfClass:[UINavigationController class]]
&& [[(UINavigationController *)secondaryViewController topViewController] isKindOfClass:[GenericResourceViewController class]]
&& ([(GenericResourceViewController *)[(UINavigationController *)secondaryViewController topViewController] resourceLoaded] == NO)) {
return YES;

} else if ([secondaryViewController isKindOfClass:[GenericResourceViewController class]]) {
return YES;
}

return NO;
}

This methods asks the delegate how it wants to fold the detail (right) view controller stack into the master (left) view controller stack.

When UISplitViewController is created in a storyboard, much of the work is done for you including creating the segues that connect the splitViewController to the master and detail view controllers. The above code tells the split view controller to make the master visible when collapsed (in portrait) if the detail's data isn't initialized. After moving this and other delegate methods to the splitViewController itself, it's now called when the splitViewController is laying out its subviews for the first time.

Ideally, I would like to move the delegate methods out of the splitViewController for reusability reasons, but what should be responsible for them? I don't want to maintain multiple UISplitViewController subclasses, especially if they just contain delegate methods. I'll look at creating dedicated controllers to place these delegate methods. The problem lies in where these are initialized. I can't create them in the app delegate or Ill be right back to square one. I had previously tried including the delegate methods in the master view controller with the same results.

If you have suggestions, please let me know on twitter @wesleydyson or in the comments.