NSNotification is being called multiple times from UITabBarController

前端 未结 2 851
北恋
北恋 2021-01-07 06:31

I have a UITabBarController, which has 4 tabs. Each one of those tabs is a separate UIViewController. I have objects on each one of those 4 VC\'s t

相关标签:
2条回答
  • 2021-01-07 07:03

    You must have implemented the NSNotificationCenter's -addObserver:selector:name:object: method in the -viewDidLoad of every viewController

    Example:

    - (void)viewDidLoad
    {
        //...
        [NSNotificationCenter defaultCenter] addObserver:self
                                                selector:@selector(doSomething:) 
                                                    name:@"TestNotification"
                                                  object:nil];
    }
    

    Instead of having this in -viewDidLoad, move it within -viewWillAppear and implement removeObserver:name:object: in -viewWillDisappear.

    This way, only the viewController that is currently on will respond to the notification.

    Example:

    - (void)viewWillAppear:(BOOL)animated
    {
        //...
        [NSNotificationCenter defaultCenter] addObserver:self
                                                selector:@selector(doSomething:) 
                                                    name:@"TestNotification"
                                                  object:nil];
    }
    
    - (void)viewWillDisappear:(BOOL)animated
    {
        //...
        [NSNotificationCenter defaultCenter] removeObserver:self
                                                       name:@"TestNotification"
                                                     object:nil];
    }
    

    - (void)doSomething:(NSNotification *)userInfo
    {
        //...
        //if you push a viewController then the following is all you need
        [self.navigationController pushViewController:vcSomething
                                             animated:YES];
    
        //however.... if you're instead presenting a viewController modally then
        //you should implement "-removeObserver:name:object: in this method as well
    
        //[NSNotificationCenter defaultCenter] removeObserver:self
        //                                               name:@"TestNotification"
        //                                             object:nil];
        //[self presentViewController:vcSomething
        //                   animated:YES
        //                 completion:nil];
    
        //OR... in the completion parameter as:
    
        //[self presentViewController:vcSomething
        //                   animated:YES
        //                 completion:^{
        //                     [NSNotificationCenter defaultCenter] removeObserver:self
        //                                                                    name:@"TestNotification"
        //                                                                  object:nil];
        //                 }];
    }
    

    EDIT:

    You (@Jonathan) commented:

    I really appreciate your answer and it has helped me out a lot! I actually ran into one more scenario where this issue occur's and I'm not sure how to figure it out. Right now I have a VC that presents another VC modally. Each one has observers for the same NSNotification. Everything performs perfectly well when I'm in the modally presented VC, but once I dismiss that VC and return to the underlying one I have the same issue where the notification is being called multiple times. Do you have an idea for a solution in this case?

    Now... regarding this...

    FIRSTLY... NOTE:

    1. Multiple -addObserver:selector:name:object: will register the specified notification multiple times (means... same notification being registered for N times will call invoke the target selector N times)
    2. Presenting a ViewController (call it Child) from, say, Parent viewController will NOT invoke the -viewWillDisappear: of the Parent
      where as...
    3. Dismissing the Child viewController will still invoke -viewWillAppear: of the Parent

    This creates an imbalance in the logic and if not handled (as per the commented lines in the code example of the doSomething method above), it results in the Parent registering for the notification multiple times (as it's -viewWillAppear: method is called more often than not -viewWillDisappear:)

    also see: similar question

    0 讨论(0)
  • 2021-01-07 07:03

    it should be called only once so that it never gets called again

    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(methodName:) name:@"name" object:nil];
    });
    
    0 讨论(0)
提交回复
热议问题