Popping Modal UINavigationController

Discussion in 'iOS Programming' started by Littleodie914, Oct 3, 2010.

  1. Littleodie914 macrumors 68000

    Littleodie914

    Joined:
    Jun 9, 2004
    Location:
    Rochester, NY
    #1
    A pretty basic question, but one that I'm having trouble finding a solid answer to. Perhaps I'm not looking in the right places?

    I have a separate XIB file containing a UINavigationController. It's in a separate XIB so it can be loaded and displayed from a number of different points in my app.

    You can see the layout of the XIB in the screenshot. Now here's the deal... I want that Cancel button to pop the UINavigationController, in any scenario. I would even be alright with providing that Cancel button as an Outlet, and forcing those who load the XIB to set the callback function.

    What's the best method to set this up? It must be a common occurrence, and if I were building the UI programmatically, it wouldn't be a problem, but I'm new to designing in IB with separate XIB files. :) I have a sneaking suspicion I need to subclass UINavigationController, provide an outlet for the UIBarButtonItem, and do something like:

    Code:
    - (void)showSyncWindow:(id)sender {
    	NSArray *nibViews =  [[NSBundle mainBundle] loadNibNamed:@"SyncViewController" owner:self options:nil];
    	for (id object in nibViews) {
    		if ([object isKindOfClass:[MyNavigationController class]]) {
                            MyNavigationController *nav = (MyNavigationController *)object;
                            nav.cancelButton.target = self; // <-- The new lines
                            nav.cancelButton.action = @selector(popWithAnimation:); // <-- The new lines
    			[self presentModalViewController:nav animated:YES];
    		}
    	}
    }
    
    
     

    Attached Files:

  2. seepel macrumors 6502

    seepel

    Joined:
    Dec 22, 2009
    #2
    Is this displayed only as a modal view controller, only on a navigation controller stack, or sometimes both? If it's always a modal view controller there is a handy property on UIViewController called parentViewController that you could use to make the modal view controller dismiss itself. If it is both you could first check if the navigation controller is nil, if not, pop the view controller, then check if the parent view controller is nil, and if not dismiss the view controller.
     
  3. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #3
    parentViewController is not needed to dismiss a modal view. You can simply call:
    Code:
    [self dismissModalViewControllerAnimated:[I]YES/NO[/I]];
     
  4. Littleodie914 thread starter macrumors 68000

    Littleodie914

    Joined:
    Jun 9, 2004
    Location:
    Rochester, NY
    #4
    I'm having issues with that method call.

    Here's a simplified version of what I'm working with:

    UINavigationController (A), currentViewController is UIViewController (B)

    in UIViewController (B), I call:

    Code:
    [self presentModalViewController:(UINavigationController *)nav animated:YES];
    nav is a second UINavigationController (C), whose currentViewController is UIViewController (D).

    How, in D, can I pop back to B? I've tried:

    Code:
    [self dismissModalViewControllerAnimated:[I]YES/NO[/I]];
    [self.parentViewController dismissModalViewControllerAnimated:[I]YES/NO[/I]];
    [self.parentViewController.navigationController dismissModalViewControllerAnimated:[I]YES/NO[/I]];
    But none of them produce results. It seems there should be an easy, static way to pop the top-most modal VC? :confused:
     
  5. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #5
    You're not actually putting YES/NO in the call, are you? You need to pick just one of the values.
     
  6. Littleodie914 thread starter macrumors 68000

    Littleodie914

    Joined:
    Jun 9, 2004
    Location:
    Rochester, NY
    #6
    Haha absolutely not, I'm using YES in all the calls. :p
     
  7. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #7
    Code:
    [self dismissModalViewControllerAnimated:YES];
    works fine to pop back from D to B in a simple test project I threw together (see attached; where D == TwoDetailViewController and B == OneDetailViewController). Perhaps there is something funky going on in your navigation stack(s).
     

    Attached Files:

  8. Littleodie914 thread starter macrumors 68000

    Littleodie914

    Joined:
    Jun 9, 2004
    Location:
    Rochester, NY
    #8
    Thank you very much for taking the time to put that project together, it's a great reference. I've taken a closer look at my setup, and the issue appears to be related to the fact that the second UINavigationController I'm showing as the modal view is loaded from a .XIB.

    Take a look at this snippet:

    Code:
    - (void)showSyncWindow:(id)sender {
    	NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:@"SyncViewController" owner:nil options:nil];
    	for (NSObject *object in nibObjects) {
    		// Part One
    		if ([object isKindOfClass:[SyncNavigationController class]]) {
    			[self presentModalViewController:(SyncNavigationController *)object animated:YES];
    		}
    		
    		// Part Two
    		if ([object isKindOfClass:[SyncViewController class]]) {
    			SyncViewController *vc = (SyncViewController *)object;
    			
    			SyncNavigationController *con = [[SyncNavigationController alloc] initWithRootViewController:vc];
    			vc.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStylePlain target:vc action:@selector(dismissModalViewControllerAnimated:)];
    			[self presentModalViewController:con animated:YES];
    		}
    	}
    }
    If Part One is used, things don't work. The button doesn't appear to do anything. (Don't worry, the button is properly connected to the exact same method as Part Two.)

    If Part Two is used instead, things work perfectly.

    So it seems if I present the existing navigation controller, something isn't hooked up properly. But if I create a brand new navigation controller, which it seems like what *should be* happening when the XIB is loaded, then things work as expected.
     
  9. Littleodie914 thread starter macrumors 68000

    Littleodie914

    Joined:
    Jun 9, 2004
    Location:
    Rochester, NY
    #9
    Hm, I scrapped the idea of keeping the UINavigationController in the XIB. The XIB now just contains my instance of the UIViewController, and whenever the modal view needs to be presented, I instantiate a new UINavigationController on the fly, injecting the UIViewController from the XIB. (Set as an IBOutlet.)

    Not sure what the original problem was, but this is easier and less headache-causing. :)
     
  10. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #10
    I'll bet it had to do with connections and/or class type settings in IB. Anyways, glad to hear you've got it solved and can move on.
     

Share This Page