首先,block的Retain Cycle编译警告只出现在ARC的工程中
一种解决方法在这里:http://blog.csdn.net/itianyi/article/details/8715857
个人感觉不是很好,于是查看苹果文档,文档中是这样描述的:
In manual reference counting mode, __block id x;
has the effect of not retaining x
. In ARC mode, __block id x;
defaults to retaining x
(just like all other values). To get the manual reference counting mode behavior under ARC, you could 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 to support iOS 4 or OS X v10.6), or set the __block
value to nil
to break the retain cycle.
The following code fragment illustrates 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 a __block
qualifier and set the myController
variable to nil
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 illustrates 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 should 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... |
} |
}; |