Question

I am trying to follow this question to setup a delegate for a login sequence:- How do I set up a simple delegate to communicate between two view controllers?

In my application I have a Main View (MESHomeViewController). I also have a login structure as follows:

  1. MESLoginNavController
  2. With a root view controller of MESWelcomeViewController
  3. There are also MESLoginViewController and MESSignupViewControllers which can be pushed to the stack.

My aim is to have a delegate method which is only called when the user logs in. I am using a delegate as I cannot use viewDidLoad as the view is often reloaded/shown on different occasions so I need to see when the user has completed the login.

The user can login via the Welcome controller (via Facebook) or the login controller (via normal methods) and via the Signup (via signup ;).

This is what I have tried to implement below: MESHomeViewController.h

#import "MESWelcomeViewController.h"

@interface MESHomeViewController : UIViewController <LoginViewControllerDelegate>

@end

In the MESHomeViewController.m I check if the user is logged in, if they are not complete the following:

NSLog(@"not logged in");
MESWelcomeViewController *loginNavVC = [self.storyboard instantiateViewControllerWithIdentifier:@"WelcomeVC"];
    loginNavVC.delegate = self;
[self presentModalViewController:loginNavVC animated:NO];

In the MESWelcomeViewController.h I have the following:

@protocol LoginViewControllerDelegate;

@interface MESWelcomeViewController : UIViewController <NSURLConnectionDataDelegate>

@property (nonatomic, weak) id<LoginViewControllerDelegate> delegate;

@end



@protocol LoginViewControllerDelegate <NSObject>

- (void)didLoginUser;

@end

Once the user is completely logged in via a custom method. MESWelcomeViewController.m once user logged in

   NSLog(@"%@",self.delegate);
    if ([self.delegate respondsToSelector:@selector(didLoginUser)]) {
        [self.delegate didLoginUser];
    }

However, the delegate method is not being called, it appears the self.delegate is Null for the welcomeViewController. I am thinking possibly I should set the delegate as the Login Nav Controller based on the above setup, but then I am not sure how to call the delegate method from a view controller currently pushed on the nav?

Was it helpful?

Solution

So just to confirm, you have MESHomeViewController, which is your primary view. From here, you push MESWelcomeViewController onto the stack. MESWelcomeViewController can perform some login stuff, and once complete, calls [self.delegate didLoginUser].

If this is the case, when you initialize the MESWelcomeViewController, you need to set the delegate. You can do this easily in several ways. You could have an init function for MESWelcomeViewController which takes in an id

-(id) init:(id<LoginViewControllerDelegate>)myDelegate {
    self = [super init];
    if (self){
        self.delegate = myDelegate;
        etc...
    }
}

Alternatively, after creating the MESWelcomeViewController, but before pushing it, set the delegate property

MESWelcomeViewController *welcomeView = [[MESWelcomeViewController alloc] init];
[welcomeView setDelegate:self];
// push view stuff

Edit:

The init function I gave there isn't automatically called, it would have to explicitly be called instead of the default initializer. If you're using storyboards, you probably should be using the alternative of setting the delegate property. I've never used storyboards before, but you should probably be able to do something like this:

MESWelcomeViewController *welcomeView = [self.storyboard instantiateViewControllerWithIdentifier:@"WelcomeVC"];
[welcomeView setDelegate:self];
[self presentModalViewController:welcomeView animated:NO];

Edit 2: Best alternative would be to use notifications instead. Anything that wants to listen adds an observer to the NSNotificationCenter, and when the event occurs, post the notification.

Example:

In MESHomeViewController's initialize or viewDidLoad, put the following:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didLoginUser) name:@"LoginCompleteNotification" object:nil];

Then whenever you complete a login, do the following:

[[NSNotificationCenter defaultCenter] postNotificationName:@"LoginCompleteNotification" object:nil];

Finally, make sure that you stop listening in the Dealloc of anything that was listening

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"LoginCompleteNotification object:nil]

OTHER TIPS

Either your ViewController gets freed by its container or you're setting the delegate property too soon.

I'd suggest adding this to the first view controller:

- (void) dealloc
{
  NSLog(@"deallocing");
}

just to rule out the first option.

To check for the second option, print loginNavVC right after setting its delegate, make sure it isn't nil.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top