development

ARC 가능 코드에서 "이 블록에서 [오브젝트]를 강력하게 캡처하면 유지주기가 발생할 수 있습니다."

big-blog 2020. 6. 21. 19:04
반응형

ARC 가능 코드에서 "이 블록에서 [오브젝트]를 강력하게 캡처하면 유지주기가 발생할 수 있습니다."


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];
    // ...
    }];

경고는 request블록 내부의 개체 사용과 관련이 있습니다 .


나 자신에게 답장 :

설명서에 대한 이해는 키워드를 사용 block하고 변수를 블록 내에서 사용한 후 nil로 설정하는 것이 좋지만 여전히 경고를 표시한다고 말합니다.

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

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

    }];

업데이트 : ' _block' 대신 '_ weak' 키워드를 사용하고 임시 변수를 사용하도록했습니다.

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

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

iOS 4도 타겟팅하려면 __unsafe_unretained대신을 사용하십시오 __weak. 동일한 동작이지만 객체가 파괴 될 때 포인터가 자동으로 nil로 설정되는 대신 매달려 있습니다.


이 요청은 요청에 대한 강력한 참조가있는 요청에 블록을 할당하기 때문에 발생합니다. 블록은 요청을 자동으로 유지하므로 주기로 인해 원래 요청이 할당 해제되지 않습니다. 말이 되나요?

__block으로 요청 객체에 태그를 지정하여 자체를 참조 할 수 있기 때문에 이상합니다. 약한 참조를 옆에 만들어서이 문제를 해결할 수 있습니다 .

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

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

블록에 자기를 유지하기 때문에 발생합니다. 블록은 자체에서 액세스되며 자체는 블록에서 참조됩니다. 유지주기가 생성됩니다.

약한 참조를 생성하여이 문제를 해결하십시오. 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];

Some times the xcode compiler has problems for identifier the retain cycles, so if you are sure that you isn't retain the completionBlock you can put a compiler flag like this:

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

-(void)someMethod {
}

When I try the solution provided by Guillaume, everything is fine in Debug mode but it crashs in Release mode.

Note that don't use __weak but __unsafe_unretained because my target is iOS 4.3.

My code crashs when setCompletionBlock: is called on object "request" : request was deallocated ...

So, this solution works both in Debug and Release modes :

// Avoiding retain cycle :
// - ASIHttpRequest object is a strong property (crashs if local variable)
// - use of an __unsafe_unretained pointer towards self inside block code

self.request = [ASIHttpRequest initWithURL:...
__unsafe_unretained DataModel * dataModel = self;

[self.request setCompletionBlock:^
{
    [dataModel processResponseWithData:dataModel.request.receivedData];        
}];

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

}];

what the difference between __weak and __block reference?


Take a look at the documentation on the Apple developer website : https://developer.apple.com/library/prerelease/ios/#documentation/General/Conceptual/ARCProgrammingGuide/Introduction.html#//apple_ref/doc/uid/TP40011029

There is a section about retain cycles at the bottom of the page.

참고URL : https://stackoverflow.com/questions/7205128/fix-warning-capturing-an-object-strongly-in-this-block-is-likely-to-lead-to-a

반응형