Search code examples
objective-cblockretain-cycle

Using method with self inside blocks


I need to execute same bunch of code in two blocks (I'm using ARC):

__weak typeof(self) weakSelf = self;
[_dataProvider doA:^(NSError *error) {
    [weakSelf handleError:error];
}];

And in a different place i call:

__weak typeof(self) weakSelf = self;
[_dataProvider doB:^(NSError *error) {
    [weakSelf handleError:error];
}];

Then I have my handler:

- (void)handleError:(NSError *)error {
    [self.refreshControl endRefreshing];
    [self.tableView reloadData];
}

Is it save to use it this way? Please do notice that handleError: method uses self inside. If not, then what is the proper approach here? BTW: self is a viewController and can be dealloced (doB: and doA: blocks are based on networking, so can be slow).


Solution

  • It is not safe to do this, even if many people a doing it like this.

    You should use the "weakSelf" pattern with blocks when it is justified. In your example the "weakSelf" pattern is not justified, because self don't have any strong reference to your block. You can use like this :

    [_dataProvider doA:^(NSError *error) {
        // here you can use self, because you don't have any strong reference to your block
    
        [weakSelf handleError:error];
    }];
    

    Use "weakSelf" pattern if you have a strong reference to your block ( with a property or an instance variable for example) and your are capturing self inside the block, example :

     @property(strong) void(^)(void) completionBlock;
    ....
    
    __weak typeof(self) weakSelf = self; 
    
        self.completionBlock = ^{
          // Don't use "self" here, it will be captured by the block and a retain cycle will be created
          // But if we use "weakSelf" here many times, it risques that it will be nil at the end of the block
          // You should create an othere strong reference to the "weakSelf"
          __strong typeof(self) strongSelf = weakSelf; 
          // here you use strongSelf ( and not "weakSelf" and especially not "self")
        };