10

这是一个的编译器警告,仅在我将 XCode 更新到 4.6 时才出现。我的代码直接取自 Apple 的文档(顺便说一句,这是我的 iOS 6 代码)。

GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];

localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
    [self setLastError:error];
    if(localPlayer.authenticated){

警告--在此块中强烈捕获 'localPlayer' 可能会导致保留周期

4

2 回答 2

25

问题是 localPlayer 对象保持对自身的强引用 - 当 localPlayer 被“捕获”以在 authenticateHandler 块中使用时,它被保留(当在块中引用objective-c对象时,ARC下的编译器调用retain为你)。现在,即使对 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 被释放时,authenticHandler 也是如此),因此无需在 authenticateHandler 中维护强引用。使用 Xcode 4.6,这不再生成您提到的警告。

于 2013-01-30T23:14:21.580 回答
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){
于 2013-01-30T22:36:01.570 回答