您的位置:首页 > 大数据 > 人工智能

Capturing 'self' strongly in this block is likely to lead to a retain cycle [duplicate]

2016-01-06 14:28 751 查看
转载至:http://stackoverflow.com/questions/17009966/capturing-self-strongly-in-this-block-is-likely-to-lead-to-a-retain-cycle

问题描述:

13down
votefavorite

8

This question already has an answer here:

capturing
self strongly in this block is likely to lead to a retain cycle 5 answers

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
vote44down
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.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: