简体   繁体   中英

Remove observer or find a better alternative to NotificationCenter ios

I have several issues about NSNotification, and lifecycle of its observers.

UPD.

I will simplify my app's logic, so it will look primitive:

The ViewController A has button "Comment" and also contains a UIView B. On this UIView we have another button "Share". Each button does what it should if the user is logged in, if not it calls the "login" method from the NSObject class "Logistic" (where the most logic is) and the popup view C appears. So I made a postNotificationName in C, to make the buttons listen to if the user logged in - do their job.

eg in viewController A

- (void) comment{
    if (<user_logged_in>){
    //do the magic
                [self removeObserver];
        } else {
            [self removeObserver];
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(comment) name:@"dismiss_popup" object:nil];
            [Logistic login];
        }
}

I do the same for the "Share" method (which is in the view B), but when I for instance press the button "Comment", then skip the C - login popup, then press the "Share" button, do the login - and after that both the "Share" and "Comment" start their actions simultaneously .

I think I should call the removeObserver

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

But how to do it in the UIView B while it still exists?

Regards .

You can modify your login method in Logistics as following:

function prototype:

+ (void)loginComplete:(void(^)(BOOL success))complete;

function itself:

+ (void)loginComplete:(void(^)(BOOL success))complete {
//login code
BOOL success = YES;//or no if it was some problems))
complete(success);//replace notification post with this
}

and finally your in viewController A:

- (void) comment{
if (<user_logged_in>){
//do the magic
            [self removeObserver];
    } else {
        [self removeObserver];
        //we don't need Notification center anymore
        [Logistic loginСomplete:^(BOOL success) {
            handle login completion
        }];
    }

}

- (IBAction)commentButton:(id)sender {
    if (!user logged in) {
        [self.logistic loginUserWithCompletion:^(id result){
            if (![result isKindOfClass:[NSError class]]) {
                [self doStuff];
            }
        }];
    } else {
        [self doStuff];
    }

To recap your problem:

  • A is a parent of B.
  • A and B call C.
  • A and B listen to C.
  • When C send notification both A and B respond but you only want one of them to respond.

I suggest letting A handle all communication with C, so if B need to talk to C it needs to go through A. This is how you can do this:

in UiViewController A

-(void) viewDidLoad{

 //Adding a notification listener should be done in initialization stage.
 [[NSNotificationCenter defaultCenter] addObserver:self 
                                          selector:@selector(dismissViewC:) 
                                              name:@"dismiss_popup" object:nil];
}
- (void) comment{
    if (<user_logged_in>){
         //proceed with comment
    } else {           
            NSNumber* caller=[NSNumber numberWithInt:COMMENT];
            [Logistic login:caller];
    }
}
-(void) dismissViewC:(NSNotification*) notify{
  (NSNumber*) callerId =[notify object];
   switch(callerId.intValue){
      case COMMENT: //proceed with comment;
      case: SHARE: [self.viewB share];
   }
}
-(void) dealloc {
    // removing an observer should be done in the dealloc stage
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

in UIView B:

 - (void) share{
        if (<user_logged_in>){
             //proceed with share
        } else {           
                NSNumber* caller=[NSNumber numberWithInt:SHARE];
                [Logistic login:caller];
        }
    }

Logistics will need to pass the new login parameter to C and C will look like this:

-(void) login:(NSNumber*) caller{
   self.myCaller=caller;
   // proceed with login
}
-(void) dismissMe{
      [[NSNotificationCenter defaultCenter] postNotificationName:@"dismiss_popup"
                                                          object:self.caller];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM