9

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;
addlistener
  • 871
  • 1
  • 12
  • 20
  • I am having the exact same problem. It's some time since you asked this question; have you come up with another solution, or are you simply stuck? I would love to hear about any progress you've made. – chrisbuchholz Jan 08 '15 at 20:21
  • @chrisbuchholz Now I thought that, dismissing the detail shouldn't be encouraged because there's no dismissing in expanded display. In my case, I hide my rightBarButtonItem to indicate that current action is performed, you need to navigate back yourself.(My detail VC is for adding some record) – addlistener Jan 10 '15 at 11:29
  • My detail view is for editing an item. If I tap my delete button in the view there's no item to edit, which makes the view useless. Right now it just invalidates the view, which is perfectly fine on iPad and on the 6 Plus in landscape, but otherwise it's useless and what should happen is that the tableview with items that brought you to the detail view should be shown. – chrisbuchholz Jan 10 '15 at 11:41

3 Answers3

3

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.

chrisbuchholz
  • 639
  • 8
  • 17
  • Buried in other stuff now...I'll test this when I get back to my project ASAP – addlistener Jan 12 '15 at 07:57
  • @jchnxu: Just pinging you. The solution should be marked as such if it in fact is a solution. If not, we should focus on improving the suggested one or finding another. – chrisbuchholz Feb 25 '15 at 09:29
3

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)
    }
}
Elardus Erasmus
  • 135
  • 1
  • 11
  • 1
    Does this code even compile for you? I get `Value of type 'UIViewController' has no member 'popToRootViewControllerAnimated'` unless I cast to UINavigationController. – Jon Brooks Apr 26 '16 at 20:37
1

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];
}
frenya
  • 239
  • 2
  • 11