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.
'development' 카테고리의 다른 글
! = 점검 스레드는 안전한가요? (0) | 2020.06.21 |
---|---|
Java 인터페이스 메소드를 추상으로 선언하는 이유는 무엇입니까? (0) | 2020.06.21 |
SQL Server에서 상수 1 또는 0으로 비트를 암시 (0) | 2020.06.21 |
.toArray (new MyClass [0]) 또는 .toArray (new MyClass [myList.size ()])? (0) | 2020.06.21 |
java.exe와 javaw.exe의 차이점 (0) | 2020.06.21 |