Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UISplitView button missing after detail replace segue

I have a master detail iPad interface set up with storyboard to provide a replace segue on the detail view controller. This works fine to replace the detail controller, however the bar button to display the master controller is missing in certain situations.

If I do the segue while in portrait, the bar button is missing because the willHideViewController: delegate method is never called. I am setting the delegate to the new detail controller when prepareForSegue: is called from the master.

When the button is missing, I can rotate the iPad to landscape then back to portrait and the button will then appear.

In prepareForSegue:

UINavigationController *nav = [segue destinationViewController];
    UIViewController *destinationViewController = nav.topViewController;
    if ([destinationViewController conformsToProtocol:@protocol(UISplitViewControllerDelegate)]) {
        self.splitViewController.delegate = destinationViewController;
    }
    else {
        self.splitViewController.delegate = nil;
    }

In the detail controllers:

#pragma mark - Split view

- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
    barButtonItem.title = NSLocalizedString(@"MasterButton", @"Master");
    [self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
    self.masterPopoverController = popoverController;
}

- (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
    // Called when the view is shown again in the split view, invalidating the button and    popover controller.
    [self.navigationItem setLeftBarButtonItem:nil animated:YES];
    self.masterPopoverController = nil;
}
like image 511
BytesGuy Avatar asked Jan 06 '14 16:01

BytesGuy


1 Answers

I finally cracked it, after looking at the iOS8 Day by Day course, namely the splitViewController chapter 18.

What happened for me was similar to this thread. Initially the SpliViewController made the DetailViewController show the 'Expand' button. After a segue, this would disappear. So the initial thought was that my SplitViewController, onViewLoad(), touched the DetailViewController. When the DetailViewController got recreated, this custom behavior would not be reproduced. Here is my Storyboard just so you can identify the objects in code more easily: enter image description here Please note both Master and Detail Controller have Navigation Controllers (I understand this is how you can get them to behave with nav bars, I don't really know though I am a hobbyist at iOS).

So after commenting some code block by block, in TopStuffSpliViewController I found the code line that made this behavior:

let detailNavVC = self.childViewControllers.last as! UINavigationController
    detailNavVC.topViewController!.navigationItem.leftBarButtonItem = self.displayModeButtonItem()

Now it was just a matter of recreating this behavior EACH TIME the DetailController loaded:

override func viewDidLoad() {
        super.viewDidLoad()
....
if (self.navigationController?.splitViewController?.collapsed == false {
    self.navigationItem.leftBarButtonItem = self.navigationController?.splitViewController?.displayModeButtonItem()}

Careful, if you ignore the if statement you will also hide the back button on the single detail controller screens like iPhone 4S! And that's it, it works as expected now!

like image 87
Radu Avatar answered Oct 22 '22 16:10

Radu