Kevin_TA
Kevin_TA

Reputation: 4675

Call popViewController from Class Method

I'd like to go back to my root view from within a class method of view 1. When in an instance method of view 1, i would just say

[self.navigationController popViewControllerAnimated:YES];

but since self doesn't apply in a class method, I am wondering how to accomplish this. Pertaining to the illustration below, I am currently in a class method of View1Controller.m and I'd like to get back to Rootview. Thanks.

enter image description here

Upvotes: 1

Views: 1025

Answers (3)

Zhang
Zhang

Reputation: 11607

You can declare another method:

-(void)closeThisViewController
{
    [self.navigationController popViewControllerAnimated:YES];   
}

Then use NotificationCenter:

[[NSNotificationCenter defaultCenter] postNotificationName:@"notif_closeThisVC" selector:@selector(closeThisViewController) object:nil];

Although as jonkroll said, you're dealing with view controller stuff, we don't understand why you would put view controller related code inside a class method.

Edit

Sorry bad code above.

I meant to say you can use NSNotificationCenter to post a notification:

-(void)postNotificationName:(NSString *)notificationName object:(id)notificationSender

Then in the same view controller declare a NSNotificationCenter observer:

- (void)addObserver:(id)notificationObserver selector:(SEL)notificationSelector name:(NSString *)notificationName object:(id)notificationSender

My brain was quicker than my fingers, so I kinda combined the two into one when I tried to explain the solution :P

It should more like this:

// posting a notification with NSNotificationCenter
[[NSNotificationCenter defaultCenter] postNotificationName:@"notif_closeThisVC" object:nil];

In your viewDidLoad method somewhere (I recommend at the top), add this:

-(void)viewDidLoad
{
    // adding an observer with NSNotificationCenter
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closeThisViewController) name:@"notif_closeThisVC" object:nil];

    ...
}

Hope that helps.

Upvotes: 2

Becca Royal-Gordon
Becca Royal-Gordon

Reputation: 17861

If you don't want to refactor this from a class method to an instance method (and there are certainly cases where you wouldn't want to do that), I'd suggest you add a completion block parameter to your class method:

+ (void)doSomethingWithCompletion:(void(^)())completion {
    /* Do your thing... */
    completion();
}

- (IBAction)doSomething:(id)sender {
     [self.class doSomethingWithCompletion:^{
          [self.navigationController popViewControllerAnimated:YES];
     }];
}

This would allow you to cleanly separate the instance-less operation the class method performs from instance-specific dismissing of the view controller. You could also make the completion block accept an error object if the operation can fail.

You could do something similar with a delegate object or even by passing in the view controller to dismiss, but this design seems to offer the cleanest separation with the most modern feel.

Upvotes: 1

ckhan
ckhan

Reputation: 4791

There are going to be legitimate arguments that encourage you to refactor so that you do have access to the current view controller and can access the navigation controller via currentVC.navigationController. Remember, it can still be a class method, just give it an extra argument when you call it (or start the call chain that calls it) from the VC.

However, I also had to solve this in one of my apps, so I just made sure that the navigation controller was globally accessible to everyone, always via pointer ("weak ref")

If you declare a global variable like this (say, in "Navigation.h")

extern UINavigationController *gNavController;

and define it in your AppDelegate.m (pays to review distinction between declaration/definition if you're rusty on that):

UINavigationController* gNavController;

and then assign it when you start up in application:didFinishLaunchingWithOptions:: (assuming the delegate has a property called viewController that is your navigation controller):

gNavController = viewController;

Then as long as you #import Navigation.h, you'll always have access to the navigation controller. This also makes getting a handle to its view for popups/popovers much simpler. This also assumes your nav controller is never released for the lifetime of the app (probably true unless you're doing something unusual).

Upvotes: 0

Related Questions