Capturing 'self' strongly in this block is likely to lead to a retain cycle [duplicate]
질문 설명:
13down votefavorite
8
This question already has an answer here:
I have reqest with block. But the compiler issues a warning
"Capturing 'self' strongly in this block is likely to lead to a retain cycle"
__weak typeof(self) weakSelf = self; [generalInstaImage setImageWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:data[@"images"][@"low_resolution"][@"url"]]] placeholderImage:[UIImage imageNamed:@"Default"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { NSLog(@"success"); [generalInstaImage setImage: image]; [weakSelf saveImage:generalInstaImage.image withName:data[@"id"]]; } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) { NSLog(@"fail"); }];
I try example write like
weakSelf.generalInstaImage
, but then the compiler generates an error and do not compile. 해결 방법:
up vote
44down voteaccepted
When you receive this warning:
Capturing
self
strongly in this block is likely to lead to a retain cycle You should review your block for:(a) any explicit references to
self
(b) any implicit references to self
caused by referencing any instance variables. Let's imagine that we have some simple class property that was a block (this will experience the same "retain cycle" warnings as your question, but will keep my examples a little simpler):
@property (nonatomic, copy) void (^block)(void);
And let's assume we had some other class property we wanted to use inside our block:
@property (nonatomic, strong) NSString *someString;
If you reference
self
within the block (in my example below, in process of accessing this property), you will obviously receive that warning about the retain cycle risk: self.block = ^{ NSLog(@"%@", self.someString); };
That is remedied via the pattern you suggested, namely:
__weak typeof(self) weakSelf = self; self.block = ^{ NSLog(@"%@", weakSelf.someString); };
Less obvious, you will also receive the "retain cycle" warning if you reference an instance variable of the class inside the block, for example:
self.block = ^{ NSLog(@"%@", _someString); };
This is because the
_someString
instance variable carries an implicit reference to self
, and is actually equivalent to: self.block = ^{ NSLog(@"%@", self->_someString); };
One might be inclined to just use
weakSelf
pattern again, resulting in the weakSelf->_someString
syntax, but the compiler will warn you about this: Dereferencing a
__weak
pointer is not allowed due to possible null value caused by race condition, assign it to strong
variable first You therefore resolve this by using the
weakSelf
pattern, but also create a local strong
variable within the block and use that to dereference the instance variable: __weak typeof(self) weakSelf = self; self.block = ^{ __strong typeof(self) strongSelf = weakSelf; if (strongSelf) { NSLog(@"%@", strongSelf->_someString); // or better, just use the property // // NSLog(@"%@", strongSelf.someString); } };
As an aside, this creation of a local
strong
reference, strongSelf
, inside the block has other advantages, too, namely that if the completion block is running asynchronously on a different thread, you don't have to worry about self
being deallocated while the block is executing, resulting in unintended consequences. This
weakSelf
/ strongSelf
pattern is very useful when dealing with block properties and you want to prevent retain cycles (aka strong reference cycles), but at the same time ensuring that self
cannot be deallocated in the middle of the execution of the completion block. FYI, Apple discusses this pattern in the "non-trivial cycles" discussion further down in the Use Lifetime Qualifiers to Avoid Strong Reference Cycles section of the Transitioning to ARC Release Notes.
You report that you received some "error" when you referenced
weakSelf.generalInstaImage
in your example. This is the correct way to resolve this "retain cycle" warning, so if you received some warning, you should share that with us, as well as show us how you declared the property.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.