EXC_BAD_ACCESS when using weakSelf in block / bloc

2019-07-15 05:11发布

I have been struggeling with this issue for a while since i don't think i fully understand the retain cycles. I am totally new to this and i'm trying to learn more about it.

I am getting the EXC_BAD_ACCESS message with the following code.

I started using the weakSelf because i get 2 warnings about the retain cycle if i just use self.successBLock();. The exact warning is:

Capturing 'self' strongly in this block is likely to lead to a retain cycle

Maybe i shouldn't even bother using the weak but i am no so sure about this.

This is the part where i use the weakSelf in a block:

__weak Request *weakSelf = self;

[_operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    weakSelf.successBlock(operation.response, responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    weakSelf.failureBlock(operation.response, error);
}];

This is how i assign the block properties:

typedef void (^successBlock)(NSHTTPURLResponse *response, id responseObject);
typedef void (^failureBlock)(NSHTTPURLResponse *response, NSError *error);

@property (nonatomic, copy) successBlock successBlock;
@property (nonatomic, copy) failureBlock failureBlock;

2条回答
干净又极端
2楼-- · 2019-07-15 05:17

A __weak reference is set to nil if the object it points to is deallocated. So if your Request object has already been deallocated when the completion block is called, weakSelf is nil. In that case weakSelf.successBlock evaluates to a NULL pointer, and that is causing the crash.

The following pattern avoids this problem:

[_operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    Request *strongSelf = weakSelf;
    if (strongSelf) {
        strongSelf.successBlock(operation.response, responseObject);
    }
} ...

strongSelf will be nil if the Request object has already been deallocated. Otherwise the strong reference ensures that the object is not deallocated while the block is executing.

On the other hand, if you want the Request object to exist until the completion block is called, then you should not use a weak reference.

查看更多
ゆ 、 Hurt°
3楼-- · 2019-07-15 05:19

When weakSelf is set to nil, weakSelf.successBlock is fine, but weakSelf.successBlock(operation.response, responseObject) will crash.

查看更多
登录 后发表回答