美文网首页
iOS闭包循环引用

iOS闭包循环引用

作者: 太郎君 | 来源:发表于2016-07-11 22:26 被阅读458次

    block的实现思想是通过建立局部变量的快照,让block中的修改不影响原始变量。在实现方式上为了能够延迟执行某个block,需要hold住相关的变量,内部会retain变量。比方说含有copy属性的block在使用_instanceObj时不会retain变量,但是会retain self,如果使用不当就会导致循环引用。

    无需解决循环引用的闭包

    可以直接使用self或者_instanceObj

    不持有block

    [UIView animateWithDuration:0.2 animations:^{
        self.alpha = 0.0f;
    } completion:^(BOOL finished) {
        [self stopLoading];
    }];
    

    同步执行

    [_messageList enumerateObjectsUsingBlock:^(TimelineMessageData *nodeData, NSUInteger index, BOOL *stop) {
        if (nodeData.svrID == msgData.svrID) {
            [_tableView reloadRow:index inSection:kSectionOffset rowAnimation:UITableViewRowAnimationNone];
            *stop = YES;
        }
    }];
    

    需要解决循环引用的闭包

    不可以直接使用self或者_instanceObj,需要做些额外的工作,常用的处理方式有两种

    使用weakSelf+strongSelf

    直接调用一个实例变量,会被编译器处理成 ‘self->theVar’,’self’ 是一个 strong 类型的变量,引用计数会加 1

    __weak __typeof__(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [weakSelf doSomething];
    });
    

    在 doSomething 中,weakSelf 不会变成 nil,不过在 doSomething 执行完成,调用第二个方法 doOtherThing 的时候,weakSelf 有可能被释放

    __weak __typeof__(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [weakSelf doSomething];
        [weakSelf doOtherThing];
    });
    

    __strong 确保在 Block 内,strongSelf 不会被释放。

    __weak __typeof__(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        __strong __typeof(self) strongSelf = weakSelf;
        [strongSelf doSomething];
        [strongSelf doOtherThing];
    });
    

    主动断开循环引用

    在如下两个block中可直接用self。

    - (void)startWithCompletionBlockWithSuccess:(void (^)(YTKBatchRequest *batchRequest))success
                                        failure:(void (^)(YTKBatchRequest *batchRequest))failure;
    - (void)setCompletionBlockWithSuccess:(void (^)(YTKBatchRequest *batchRequest))success
                                  failure:(void (^)(YTKBatchRequest *batchRequest))failure;
    

    因为在回调函数中主动断开了循环引用。

    - (void)handleRequestResult:(AFHTTPRequestOperation *)operation {
        NSString *key = [self requestHashKey:operation];
        YTKBaseRequest *request = _requestsRecord[key];
        YTKLog(@"Finished Request: %@", NSStringFromClass([request class]));
        if (request) {
            BOOL succeed = [self checkResult:request];
            if (succeed) {
                [request toggleAccessoriesWillStopCallBack];
                [request requestCompleteFilter];
                if (request.delegate != nil) {
                    [request.delegate requestFinished:request];
                }
                if (request.successCompletionBlock) {
                    request.successCompletionBlock(request);
                }
                [request toggleAccessoriesDidStopCallBack];
            } else {
                YTKLog(@"Request %@ failed, status code = %ld",
                         NSStringFromClass([request class]), (long)request.responseStatusCode);
                [request toggleAccessoriesWillStopCallBack];
                [request requestFailedFilter];
                if (request.delegate != nil) {
                    [request.delegate requestFailed:request];
                }
                if (request.failureCompletionBlock) {
                    request.failureCompletionBlock(request);
                }
                [request toggleAccessoriesDidStopCallBack];
            }
        }
        [self removeOperation:operation];
        [request clearCompletionBlock];
    }
    
    - (void)cancelRequest:(YTKBaseRequest *)request {
        [request.requestOperation cancel];
        [self removeOperation:request.requestOperation];
        [request clearCompletionBlock];
    }
    
    - (void)clearCompletionBlock {
        self.successCompletionBlock = nil;
        self.failureCompletionBlock = nil;
    }
    

    相关文章

      网友评论

          本文标题:iOS闭包循环引用

          本文链接:https://www.haomeiwen.com/subject/yupjjttx.html