Xcode 4.6 ARC Advertencia para la authentication del Game Center

Esta es una nueva advertencia del comstackdor que solo apareció cuando actualicé XCode a 4.6. Mi código se levanta directamente de la documentation de Apple (este es mi código de iOS 6 por cierto).

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

Advertencia: capturar fuertemente 'localPlayer' en este bloque probablemente conduzca a un ciclo de retención

El problema es que el object localPlayer mantiene una fuerte reference a sí mismo: cuando localPlayer se "captura" para su uso dentro del bloque authenticateHandler, se retiene (cuando los objects objective-c se denominan dentro de un bloque, el comstackdor en las llamadas ARC retiene para ti). Ahora, incluso cuando todas las demás references al localPlayer dejen de existir, todavía tendrá un recuento de retención de 1 y, por lo tanto, la memory nunca se liberará. Es por eso que el comstackdor te está dando una advertencia.

Consíguelo con una reference débil, como:

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

Dado que la vida útil de authenticateHandler y localPlayer está estrechamente vinculada (es decir, cuando el localPlayer se desasigna, también lo es el authenticateHandler), no es necesario que mantenga una reference sólida dentro de authenticateHandler. Usando Xcode 4.6, esto ya no genera la advertencia que mencionaste.

El comstackdor solo te está ayudando con código que ya era un problema, simplemente no lo sabía antes.

Puede leer sobre retener ciclos aquí: http://www.cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html

Básicamente solo necesitas cambiar tu código a algo así:

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