Search code examples
iosobjective-ccocoaobjective-c-blocks

Correct management of addObserverForName:object:queue:usingBlock:


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 removeObserver:name:object:

-(void) scan {
    Scanner *scanner = [[Scanner alloc] init];
    id scanComplete = [[NSNotificationCenter defaultCenter] addObserverForName:@"ScanComplete" 
                        object:scanner 
                        queue:nil 
                        usingBlock:^(NSNotification *notification){
                            /*
                             do something
                             */
                            [[NSNotificationCenter defaultCenter] removeObserver:scanComplete];
                            [scanner release];
                        }];
    [scanner startScan];
}

Update: I'm receiving intermittent EXC_BAD_ACCESS from this block, so this can't be right.


Solution

  • 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];
    }