ARC des collisions liées à iOS lors de l'utilisation d'un pointeur de bloc comme une variable membre

Quelqu'un peut s'il vous plaît aider avec l'ARC et la mémoire des blocages liés à l'?

J'ai la classe LTRequest avec un membre de la variable qui stocke un pointeur de bloc:

typedef void (^APICallOKBlock)(id);

@interface LTRequest : NSObject
@property (nonatomic, strong) APICallOKBlock okCB;
@end

Le code d'initialisation de cette variable:

-(void)addOKBlock:(APICallOKBlock)okBlock
{
    self.okCB = okBlock;
}

J'appelle le bloc en cas de succès:

-(void)apiCallCompletedWithResult:(id)result
{
    if(self.okCB != nil)
    {
        self.okCB(result);
    }
}

Pour référence, le bloc ressemble à quelque chose comme ceci:

APICallOKBlock okBlock = ^(id result)
{
    [self handleAPICallCompleted:result];
};

Il appelle une fonction définie dans l'objet qui a planifié l'appel d'api, toutefois, la partie n'est pas important. L'Important est ce qui se passe quand apiCallCompletedWithResult est appelée après l'appel de l'api a été couronnée de succès. Et ce qui se passe est que le bloc est appelé, mais l'application se bloque peu de temps après, lorsque l'objet de la requête LTRequest obtient libéré (SomeAppName est notre application):

Thread 6 name:  Dispatch queue: com.apple.root.low-priority
Thread 6 Crashed:
0   libobjc.A.dylib                 0x300bad9c objc_release + 12
1   libobjc.A.dylib                 0x300c6c00 objc_storeStrong + 24
2   SomeAppName                     0x00055688 -[LTRequest .cxx_destruct] (LTRequest.m:12)
3   libobjc.A.dylib                 0x300bba66 object_cxxDestructFromClass + 50
4   libobjc.A.dylib                 0x300bba2c object_cxxDestruct + 8
5   libobjc.A.dylib                 0x300b99ac objc_destructInstance + 20

J'ai essayé d'utiliser unsafe_unretained au lieu de strong pour stocker le bloc dans la LTRequest objet:

@property (nonatomic, unsafe_unretained) APICallOKBlock okCB;

Dans ce cas, le crash se passe exactement dans la ligne avec le si:

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libobjc.A.dylib                 0x300b9eda objc_retain + 10
1   libobjc.A.dylib                 0x300c6bde objc_retainAutoreleasedReturnValue + 34
2   SomeAppName                     0x00054f90 -[LTRequest apiCallCompletedWithResult:] (LTRequest.m:84)
3   SomeAppName                     0x0002f8aa __29-[LTServerProxy makeAPICall:]_block_invoke_0 (LTServerProxy.m:154)

//file LTRequest.m

line 84    if(self.okCB != nil)
line 85    {
line 86        self.okCB(result);
line 87    }

Suis-je utiliser le pointeur vers un bloc correctement et comment dois-je l'appeler pour ne pas causer de tout les crashs?

Quelques infos: je suis en utilisant SDK iOS 5.0, cible de déploiement est 4.0, un appareil iPhone, et l'ARC est activé pour l'ensemble du projet.

OriginalL'auteur Amiramix | 2012-01-13