Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically dismiss detail view controller in collapsed display?

Question

In a UISplitViewController collapsed display, how can I programmatically get back to master view controller?

Detail

I googled it but found no solution. Not sure if I was using the right keyword. This is how I show the detail view controller:

[self showDetailViewController:[[UINavigationController alloc] initWithRootViewController:detail] sender:self];

I also tried these 3 methods respectively, but none of them worked:

if (self.splitViewController.collapsed) {
        UIBarButtonItem *backButtonItem = self.navigationItem.leftBarButtonItem;
        (1):[backButtonItem.target performSelector:backButtonItem.action];
        (2):[[UIApplication sharedApplication] sendAction:backButtonItem.action to:backButtonItem.target from:nil forEvent:nil];
        (3):objc_msgSend(backButtonItem.target, backButtonItem.action);
}

navigation items set like thie in detail VC viewDidLoad:

self.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
self.navigationItem.leftItemsSupplementBackButton = YES;
like image 743
jchnxu Avatar asked Dec 23 '14 13:12

jchnxu


3 Answers

Alright, I have found a solution that seems to work. I have tested it on iPhone 6 and iPhone 6 Plus, but I only just discovered it thirty minutes ago, so It might have some unfortunate side effect which I have not run into yet.

It's in swift. I hope it's clear though. Let me know if you need me to provide it in Objective-C instead.

if let splitViewController = splitViewController {
    if splitViewController.collapsed {
        let viewControllers = splitViewController.viewControllers
        for controller in viewControllers {
            // PrimaryNavigationController is the navigation controller I use
            // as the split views master view, which is also set as its delegate
            // but it could be any UINavigationController that is the
            // primary controller of the split view
            if controller.isKindOfClass(PrimaryNavigationController) {
                controller.popViewControllerAnimated(true)
            }
        }
    }
}

I call this from my detail view when I want to dismiss it.

The code works by checking if the split view controller is collapsed, which is the only state where popping the detail view makes sense (to me anyways). Then it simply looks for the navigation controller currently in play in the split view controller and asks it to pop it's top view controller. This works because when in collapsed mode, the split views master view is the only view controller in the stack. The detail view is collapsed "into" it, and therefore becomes the current top view controller of it, thus is the one that gets popped.

Seems to work. Let me know if it do for you too.

like image 120
chrisbuchholz Avatar answered Nov 08 '22 18:11

chrisbuchholz


I was looking to do exactly the same, and this code worked for me. I put it in the detail view, hooked up to a button in the navigation bar.

In my application the detail view can segue to itself a number of times and this code gets one back to the master view no matter how deep down the line it gets.

@IBAction func unwindSegueId(sender: AnyObject) {
    if (self.splitViewController!.collapsed) {
        self.splitViewController!.viewControllers[0].popToRootViewControllerAnimated(true)
    }
}
like image 22
Elardus Erasmus Avatar answered Nov 08 '22 18:11

Elardus Erasmus


This seems to work (provided you have a navigation controller in your master pane)

if (self.splitViewController.collapsed) {
    [(UINavigationController *)self.splitViewController.viewControllers[0]
     popToRootViewControllerAnimated:YES];
}
like image 30
frenya Avatar answered Nov 08 '22 19:11

frenya