Correct management of addObserverForName:object:queue:usingBlock:

后端 未结 4 505
礼貌的吻别
礼貌的吻别 2021-02-01 03:37

I\'m still new to blocks in objective-c and wondering if I have this psuedo code correct. I\'m not sure if it\'s enough to just remove the observer or if i have to call removeOb

相关标签:
4条回答
  • 2021-02-01 04:19

    The scope of the block doesn't have permission to release the scanner object. If you're not using garbage collection, removing the release and making the scanner autorelease ([[[Scanner alloc] init] autorelease]) should do the trick.

    You should also be able to safely move the call to removeObserver outside of the block.

    For the case of EXC_BAD_ACCESS: Entering bt in the console window after the application crashes will give you a backtrace, and should inform you where the error occurred.

    0 讨论(0)
  • 2021-02-01 04:20

    Apple Document about this method:

    The following example shows how you can register to receive locale change notifications.

    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
    self.localeChangeObserver = [center addObserverForName:NSCurrentLocaleDidChangeNotification object:nil
        queue:mainQueue usingBlock:^(NSNotification *note) {
    
            NSLog(@"The user's locale changed to: %@", [[NSLocale currentLocale] localeIdentifier]);
        }];
    

    To unregister observations, you pass the object returned by this method to removeObserver:. You must invoke removeObserver: or removeObserver:name:object: before any object specified by addObserverForName:object:queue:usingBlock: is deallocated.

    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    [center removeObserver:self.localeChangeObserver];
    
    0 讨论(0)
  • 2021-02-01 04:25

    You should not unregister in the register block. Instead, store the token returned from addObserverForName (in this case, your scanComplete) as an instance variable or in a collection that is an instance variable, and unregister later when you're about to go out of existence (e.g. in dealloc). What I do is keep an NSMutableSet called observers. So:

    id ob = [[NSNotificationCenter defaultCenter] 
         addObserverForName:@"whatever" object:nil queue:nil 
         usingBlock:^(NSNotification *note) {
            // ... whatever ...
    }];
    [self->observers addObject:ob];
    

    And then later:

    for (id ob in self->observers)
        [[NSNotificationCenter defaultCenter] removeObserver:ob];
    self->observers = nil;
    
    0 讨论(0)
  • 2021-02-01 04:26

    Declare the scanComplete variable before defining the block itself.

    The reason why you need to do this is because you're trying to access a variable that doesn't exist within the block at the time of definition since the variable itself has not been assigned yet.

    What is EXC_BAD_ACCESS? Well, it's an exception that is thrown when you try to access a reference that doesn't exist. So that is exactly the case in your example.

    So if you declare the variable before the block itself, then it should work:

    -(void) scan {
        Scanner *scanner = [[Scanner alloc] init];
        __block id scanComplete;
        scanComplete = [[NSNotificationCenter defaultCenter] addObserverForName:@"ScanComplete" 
                            object:scanner 
                            queue:nil 
                            usingBlock:^(NSNotification *notification){
                               /*
                               do something
                               */
                               [[NSNotificationCenter defaultCenter] removeObserver:scanComplete];
                               [scanner release];
                        }];
        [scanner startScan];
    }
    
    0 讨论(0)
提交回复
热议问题