It appears that you're trying to let the detail view controller handle marking itself as "empty."
I'd suggest moving that logic to the master view controller, so it can also handle other cases besides rotation, such as when new results arrive, or the user searches (filters) results.
Let the master view controller handle updating the detail view (either by marking its details as nil, or preferably passing it new details).
Your split view controller delegate will be able to determine how to handle the secondary view controller, and your detail view controller code will also be easier to maintain, since it won't have knowledge of, or be (tightly) coupled to a data source.
Update:
There is no master-only UISplitViewController
displayMode
where the secondary can't be shown. Display modes all show the secondary VC, but may show, hide, or overlay the primary VC. The user may rotate the device, or display or hide the primary VC (via presentsWithGesture
or displayModeButtonItem
), but the secondary VC will always shown, blank or not, for a regular size class.
Here's how Apple's Master-Detail template code determines if the secondary VC should be collapsed or discarded, when the device transitions to a horizontally compact size class.
- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {
if ([secondaryViewController isKindOfClass:[UINavigationController class]] && [[(UINavigationController *)secondaryViewController topViewController] isKindOfClass:[YHWHDetailViewController class]] && ([(YHWHDetailViewController *)[(UINavigationController *)secondaryViewController topViewController] detailItem] == nil)) {
// Return YES to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
return YES;
} else {
return NO;
}
}
Note that Apple uses a property on the detail view controller as a flag.
I understand you believe the decision whether the secondary VC should be collapsed or discarded should be based on whether the user explicitly dismissed the secondary VC (while collapsed in a horizontally compact size).
I understand that you're trying to make the detail VC "clear" itself when it disappears, but assuming it's been dismissed (discarded) and you're not holding a strong reference to it, that would be a non-operation.
It's simpler if the detail goes out of existence (or the dataSource
invalidates the detail).
If you're holding on to it, and can't clear the details, you'll either have to:
- Keep some type of flag (whether a BOOL or nil object) which reflects if the detail's content has been made "irrelevant," and rely that flag to determine in the future if the secondary view controller should (once again) be collapsed or not.
- Check the detail (before collapsing it again) against against the
dataSource
to see if it's content is "relevant" or "irrelevant."
If you use a detail VC property as the flag, here's the benefit. When the SVC is collapsed, and the detail VC has been "expressly dismissed," there's no longer a secondary VC to split from the primary VC.
- (UIViewController *)splitViewController:(UISplitViewController *)splitViewController
separateSecondaryViewControllerFromPrimaryViewController:(UIViewController *)primaryViewController{
if ([primaryViewController isKindOfClass:[UINavigationController class]]) {
for (UIViewController *controller in [(UINavigationController *)primaryViewController viewControllers]) {
if ([controller isKindOfClass:[UINavigationController class]] && [[(UINavigationController *)controller visibleViewController] isKindOfClass:[DetailViewController class]]) {
return controller;
}
}
}
// No detail view present
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UINavigationController *secondaryViewController = [storyboard instantiateViewControllerWithIdentifier:@"SecondaryViewController"];
// Ensure back button is enabled
UIViewController *detailViewController = [secondaryViewController visibleViewController];
detailViewController.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
detailViewController.navigationItem.leftItemsSupplementBackButton = YES;
return secondaryViewController;
}
Because you instantiate a "blank" detail VC, when the user rotates the SVC back from regular size to compact size, the SVC delegate can see that there are no details to display, so it discards the secondary VC.
That's Apple's approach, and it works really well, because it leaves the control over whether the SVC is collapsed or expanded to the user, via a rotation, a gesture, or the display mode button.
I'm sure you've seen Apple's mail app on the 6 Plus. Note, though, of what Apple does once the user rotates back to a regular size class. Even if the user pops back to the list of messages, the previously selected message is still shown when the detail reappears.
If it's possible to make your app also behave that way, I'd encourage it. It's friendly, convenient, and rewarding, because it saves the user time from having to make a (re)selection, and shows details instead of a blank view.