I was always using __weak
references to self
when I was in a block in GCD
. Everyone recommends that. I know that strong reference to self
(tested) in GCD can't produce retain cycles. Apple recommends using a __weak
reference to self and then a __strong
reference to that _week
reference to guarantee that self
won't be nil
when the block is executed.
I have the following piece of code:
- (IBAction)startGCD:(id)sender {
GCDVC* __weak weakSelf = self;
[self.activityIndicator startAnimating];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ // 1
// VC2* __strong strongSelf = weakSelf;
[weakSelf.proArray addObject:@"2"];
[NSThread sleepForTimeInterval:10];
NSLog(@"%@",weakSelf.proArray);
dispatch_async(dispatch_get_main_queue(), ^{ // 2
[weakSelf.activityIndicator stopAnimating];
});
});
}
Test 1 I press the button and the Indicator is spinning. I press the back button before the GCD finish and the GCDViewController is being released.
Test 2 Then I uncomment the strong reference to self and I execute the same procedure. The GCDViewController is not released until the block has finished it work. But then its released.
Test 3 Now if I refer directly to self (without __weak
or __strong
) I have the exact behaviour with Test 2.
So if I want to make sure that the self won't be nil when the block is executed what's the point of using a __strong
reference to a __weak
reference to self
? Do I miss something here? Is any example that would change the result of Test 2 & 3?
I was always using __weak references to self when I was in a block in GCD. Everyone recommends that.
No. I don't know anyone that recommends that. Weak references make sense in some situations where there would be retain cycles. But whether a block should capture a weak or strong reference to any object (including the one self
points to) depends on the particular memory management design of the code in question and
I know that strong reference to self (tested) in GCD can't produce retain cycles.
Passing a block to dispatch_async
on a global or main queue will NEVER produce a retain cycle.
Now if I refer directly to self (without __weak or __strong) I have the exact behaviour with Test 2.
Maybe you don't see any difference in this case. But they have different behavior in general. Basically, your question is what is the difference between the block capturing a strong or weak reference to the object pointed to by self
.
The difference is in what happens, if the current object (object pointed to by self
) has been released by every other object that holds a strong reference to it, except potentially the block, and the block is executed afterwards asynchronously.
nil
at this point, and the block is not going to do anything with it (it is either going to check strongSelf
and return when it sees that it is nil
, or it will send messages to strongSelf
which is nil
which does nothing). So in one case stuff is done and in the other case nothing is done.
If the current object in your case is some UI element, like a view or view controller, then as long as it is in the view hierarchy, it is going to be retained by things in the view hierarchy, so you need to exit out of this view/view controller in order to have the situation where nothing else has a strong reference to it.
In your case, all you do inside the block is [weakSelf.activityIndicator stopAnimating];
, ie a change to the UI. It doesn't matter whether this command is run or not, because, remember, the view containing this has already stopped displaying. Nobody can see this activity indicator. So what difference does it make if you stop it or not? But this is specific to this case. In general, you can imagine that the command inside the block changes some global state, or sends something over the network or something, where there is a big difference between if you do it or not.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.