First, the block's retain cycle compilation warning only appears in the ARC project.
A solution here: http://blog.csdn.net/itianyi/article/details/8715857
I personally don't feel very good, so I checked the apple documentation and described it as follows:
In manual reference counting mode,__block id x;
Has the effect of not retainingx
. In Arc
Mode,__block id x;
Defaults to retainingx
(Just like all other values). To get the manual
Reference counting mode behavior under Arc, you cocould use__unsafe_unretained __block id x;
. As the name__unsafe_unretained
Implies,
However, having a non-retained variable is dangerous (because it can dangle) and is therefore discouraged. Two better options are to either use__weak
(If you don't need
Support IOS 4 or OS X v10.6), or set__block
Valuenil
To break the retain cycle.
The following code fragment extends strates this issue using a pattern that is sometimes used in manual reference counting.
MyViewController *myController = [[MyViewController alloc] init…]; |
// ... |
myController.completionHandler = ^(NSInteger result) { |
[myController dismissViewControllerAnimated:YES completion:nil]; |
}; |
[self presentViewController:myController animated:YES completion:^{ |
[myController release]; |
}]; |
As described, instead, you can use__block
Qualifier and setmyController
Variable
Tonil
In the completion handler:
MyViewController * __block myController = [[MyViewController alloc] init…]; |
// ... |
myController.completionHandler = ^(NSInteger result) { |
[myController dismissViewControllerAnimated:YES completion:nil]; |
myController = nil; |
}; |
Alternatively, you can use a temporary__weak
Variable. The following example extends strates a simple implementation:
MyViewController *myController = [[MyViewController alloc] init…]; |
// ... |
MyViewController * __weak weakMyViewController = myController; |
myController.completionHandler = ^(NSInteger result) { |
[weakMyViewController dismissViewControllerAnimated:YES completion:nil]; |
}; |
For non-trivial cycles, however, you shoshould use:
MyViewController *myController = [[MyViewController alloc] init…]; |
// ... |
MyViewController * __weak weakMyController = myController; |
myController.completionHandler = ^(NSInteger result) { |
MyViewController *strongMyController = weakMyController; |
if (strongMyController) { |
// ... |
[strongMyController dismissViewControllerAnimated:YES completion:nil]; |
// ... |
} |
else { |
// Probably nothing... |
} |
}; |
I personally prefer the method in the Apple documentation: using a temporary variable with weak reference, or using a block variable with a post-Nil