这是一个 new 编译器警告,只有在我将XCode更新为4.6时才出现。我的代码直接取自Apple的文档(这是我的iOS 6代码btw)。
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
[self setLastError:error];
if(localPlayer.authenticated){
警告 - 捕获' localPlayer'该块中的强烈可能导致保留周期
答案 0 :(得分:25)
问题是localPlayer对象保持对自身的强引用 - 当localPlayer被“捕获”以在authenticateHandler块中使用时,它被保留(当在块中引用objective-c对象时,编译器在ARC电话为您保留)。现在,即使对localPlayer的所有其他引用都不再存在,它仍将保留计数为1,因此永远不会释放内存。这就是编译器给你一个警告的原因。
请参考弱引用,例如:
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
__weak GKLocalPlayer *blockLocalPlayer = localPlayer;
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
[self setLastError:error];
if (blockLocalPlayer.authenticated) {
...
鉴于authenticateHandler和localPlayer的生命周期紧密相关(即当localPlayer被解除分配时,authenticateHandler也是如此),因此不需要在authenticateHandler中维护强引用。使用Xcode 4.6,这不再生成您提到的警告。
答案 1 :(得分:1)
编译器只是帮助你解决已经存在问题的代码,它之前并不知道。
您可以在此处阅读有关保留周期的信息:http://www.cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html
基本上你只需要将代码更改为:
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
__weak MyViewController *blockSelf = self;
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
[blockSelf setLastError:error];
if(localPlayer.authenticated){