修复警告"在此块中强烈捕获[某个对象]可能会导致启用ARC的代码中的保留周期"

Gui*_*ume 140 cocoa cocoa-touch retain asihttprequest automatic-ref-counting

在启用ARC的代码中,如何在使用基于块的API时修复有关潜在保留周期的警告?

警告:
Capturing 'request' strongly in this block is likely to lead to a retain cycle

由这段代码生成:

ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:...

[request setCompletionBlock:^{
    NSDictionary *jsonDictionary = [[CJSONDeserializer deserializer] deserialize:request.rawResponseData error:nil];
    // ...
    }];
Run Code Online (Sandbox Code Playgroud)

警告与request块内对象的使用相关联.

Gui*_*ume 164

回复自己:

我对文档的理解是说使用关键字block并在块中使用后将变量设置为nil应该没问题,但它仍然显示警告.

__block ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:...

[request setCompletionBlock:^{
    NSDictionary *jsonDictionary = [[CJSONDeserializer deserializer] deserialize:request.responseData error:nil];
    request = nil;
// ....

    }];
Run Code Online (Sandbox Code Playgroud)

更新:让它使用关键字'_ weak'而不是' _block',并使用临时变量:

ASIHTTPRequest *_request = [[ASIHTTPRequest alloc] initWithURL:...
__weak ASIHTTPRequest *request = _request;

[request setCompletionBlock:^{
    NSDictionary *jsonDictionary = [[CJSONDeserializer deserializer] deserialize:request.responseData error:nil];
    // ...
    }];
Run Code Online (Sandbox Code Playgroud)

如果您还想要定位iOS 4,请使用__unsafe_unretained而不是__weak.相同的行为,但指针保持悬空而不是在对象被销毁时自动设置为nil.

  • 基于ARC文档,听起来你需要一起使用__unsafe_unretained __block来获得与使用ARC和块时相同的行为. (8认同)
  • @SeanClarkHess:当我合并前两行时,我收到此警告:"将保留对象分配给弱变量;对象将在赋值后释放" (4认同)
  • 有人可以解释为什么你需要__block和__weak关键字?我想有一个保留周期正在创建,但我没有看到它.如何创建临时变量来解决问题? (3认同)
  • 我发布了一个跟进问题:http://stackoverflow.com/questions/8859649/asihttprequest-asiformdatarequest-referencing-request-object-within-blocks-u (2认同)

ZaB*_*anc 49

出现此问题是因为您正在为请求分配一个块,该请求具有对其中的请求的强引用.该块将自动保留请求,因此原始请求将不会因循环而解除分配.合理?

这很奇怪,因为您使用__block标记请求对象,因此它可以引用自身.您可以通过创建一个弱引用解决这个问题一起吧.

ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:...];
__weak ASIHTTPRequest *wrequest = request;

[request setCompletionBlock:^{
    NSDictionary *jsonDictionary = [[CJSONDeserializer deserializer] deserialize:wrequest.rawResponseData error:nil];
    // ...
    }];
Run Code Online (Sandbox Code Playgroud)


HDd*_*per 12

它是由于将自我保留在块中而引起的.块将从self访问,self在块中引用.这将创建一个保留周期.

尝试通过创建弱引用来解决这个问题 self

__weak typeof(self) weakSelf = self;

operationManager = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operationManager.responseSerializer = [AFJSONResponseSerializer serializer];
[operationManager setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

    [weakSelf requestFinishWithSucessResponseObject:responseObject withAFHTTPRequestOperation:operation andRequestType:eRequestType];

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    [weakSelf requestFinishWithFailureResponseObject:error withAFHTTPRequestOperation:operation andRequestType:eRequestType];
}];
[operationManager start];
Run Code Online (Sandbox Code Playgroud)


GOr*_*o58 6

有时候xcode编译器的标识符有保留周期的问题,所以如果你确定你没有保留completionBlock,你可以放一个像这样的编译器标志:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-retain-cycles"
#pragma clang diagnostic ignored "-Wgnu"

-(void)someMethod {
}
Run Code Online (Sandbox Code Playgroud)