Conserver le cycle sur un bloc Obj-C en utilisant lui-même

J'ai un bloc à utiliser en tant que completionHandler pour une requête asynchronous NSURLConnection dont le travail principal est de générer une nouvelle requête asynchronous en utilisant le même bloc pour le nouveau gestionnaire d'achèvement de requêtes. Je le fais parce qu'il résout efficacement un autre problème qui consiste à aligner une séquence d'appels asynchronouss et de les triggersr en arrière-plan. Cela fonctionne merveilleusement bien pour nous, mais nous avons un avertissement qui me préoccupe. À savoir, XCode pense que j'ai un cycle de retenue. Peut-être que je le fais, je ne sais pas. J'ai essayé d'en savoir plus sur les blocs au cours des deux dernières heures, mais je n'ai pas trouvé d'explication pour des utilisations récursives comme la mienne. Les états d'avertissement `Bloc seront conservés par l'object capturé '.

Ma meilleure estimation jusqu'ici est qu'un cycle de rétention est exactement ce que nous voulons, et que pour effacer quand nous avons fini, nous venons de nillifier la variable de bloc, ce que je fais. Cela ne me débarrasse pas de l'erreur, mais cela ne me dérange pas tant que je ne perds pas la memory ou ne fais pas de la magie noire dont je ne suis pas conscient. Quelqu'un peut-il répondre à cela? Est-ce que je le manipule correctement? Si non, que devrais-je faire?

void (^ __block handler)(NSURLResponse *, NSData *, NSError*); handler = ^(NSURLResponse *response, NSData *data, NSError *error) { [dataArray addObject:data]; if (++currentRequestIndex < [requestsArray count]) { if (error) { [delegate requestsProcessWithIdentifier:_identifier processStoppedOnRequestNumber:currentRequestIndex-1 withError:error]; return; } [delegate requestsProcessWithIdentifier:_identifier completedRequestNumber:currentRequestIndex-1]; // completed previous request [NSURLConnection sendAsynchronousRequest:[requestsArray objectAtIndex:currentRequestIndex] queue:[NSOperationQueue mainQueue] completionHandler:handler]; // HERE IS THE WARNING } else { [delegate requestsProcessWithIdentifier:_identifier completedWithData:dataArray]; handler = nil; } }; [NSURLConnection sendAsynchronousRequest:[requestsArray objectAtIndex:0] queue:[NSOperationQueue mainQueue] completionHandler:handler]; 

Essayez de stocker votre bloc handler dans une variable d'instance de votre controller de vue (ou de la class dans laquelle vous vous trouvez).

En supposant que vous _hander une variable d'instance nommée _hander :

 { void (^_handler)(NSURLResponse *, NSData *, NSError*); } 

Changez votre code pour:

 __weak __typeof(&*self)weakSelf = self; _handler = ^(NSURLResponse *response, NSData *data, NSError *error) { [dataArray addObject:data]; if (++currentRequestIndex < [requestsArray count]) { if (error) { [delegate requestsProcessWithIdentifier:_identifier processStoppedOnRequestNumber:currentRequestIndex-1 withError:error]; return; } [delegate requestsProcessWithIdentifier:_identifier completedRequestNumber:currentRequestIndex-1]; // completed previous request __strong __typeof(&*self)strongSelf = weakSelf; [NSURLConnection sendAsynchronousRequest:[requestsArray objectAtIndex:currentRequestIndex] queue:[NSOperationQueue mainQueue] completionHandler:strongSelf->_handler]; } else { [delegate requestsProcessWithIdentifier:_identifier completedWithData:dataArray]; } }; [NSURLConnection sendAsynchronousRequest:[requestsArray objectAtIndex:0] queue:[NSOperationQueue mainQueue] completionHandler:_handler]; 
 void (^handler)(NSURLResponse *, NSData *, NSError*); typeof(handler) __block __weak weakHandler; weakHandler = handler = ^(NSURLResponse *response, NSData *data, NSError *error) { [dataArray addObject:data]; if (++currentRequestIndex < [requestsArray count]) { if (error) { [delegate requestsProcessWithIdentifier:_identifier processStoppedOnRequestNumber:currentRequestIndex-1 withError:error]; return; } [delegate requestsProcessWithIdentifier:_identifier completedRequestNumber:currentRequestIndex-1]; // completed previous request [NSURLConnection sendAsynchronousRequest:[requestsArray objectAtIndex:currentRequestIndex] queue:[NSOperationQueue mainQueue] completionHandler:weakHandler]; // HERE IS THE WARNING } else { [delegate requestsProcessWithIdentifier:_identifier completedWithData:dataArray]; } };