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.
例如,在MRC&ARC下,以下代码会存在强引用环:
MyViewController *myController = [[MyViewController alloc] init…]; // ... myController.completionHandler = ^(NSInteger result) { [myController dismissViewControllerAnimated:YES completion:nil]; };
在MRC下,解决上述强引用环的方法如下:
MyViewController * __block myController = [[MyViewController alloc] init…]; // ... myController.completionHandler = ^(NSInteger result) { [myController dismissViewControllerAnimated:YES completion:nil]; myController = nil; };
在ARC下,解决上述强引用环的方法如下:
1 MyViewController *myController = [[MyViewController alloc] init…]; 2 // ... 3 MyViewController * __weak weakMyViewController = myController; 4 myController.completionHandler = ^(NSInteger result) { 5 [weakMyViewController dismissViewControllerAnimated:YES completion:nil]; 6 };
更好的方式是在使用__weak变量前,先用__strong变量把该值锁定,类似使用weak_ptr一样。
1 MyViewController *myController = [[MyViewController alloc] init…]; 2 // ... 3 MyViewController * __weak weakMyController = myController; 4 myController.completionHandler = ^(NSInteger result) { 5 MyViewController *strongMyController = weakMyController; 6 if (strongMyController) { 7 // ... 8 [strongMyController dismissViewControllerAnimated:YES completion:nil]; 9 // ... 10 } 11 else { 12 // Probably nothing... 13 } 14 };