La requête asynchronous ne passe pas dans le bloc d'achèvement

Le code suivant est une tentative de mieux comprendre [NSURLConnection sendAsynchronousRequest:queue:completionHandler] .

Il existe des instructions NSLog dans le bloc completionHandler , mais lorsque je l'exécute dans main.m dans XCode à partir d'un projet de command line, il ne pénètre jamais dans les blocs completionHandler . J'ai essayé d'utiliser les différentes files d'attente, mainQueue et currentQueue mais aucun travail.

Mon intuition est que la queue est désaffectée avant que la request soit terminée et que des cycles de retenue soient impliqués.

 #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { NSCache *myCache = [[NSCache alloc] init]; NSArray *images = @[ @"http://i.stack.imgur.com/E66qr.png", @"http://www.tiempoyquimera.com/wp-content/uploads/2010/01/Euro-Trash-Girl-2010.jpg", @"http://1.bp.blogspot.com/-Mxd8AB2nbQY/UYCISJiQz3I/AAAAAAAAAH8/Tc43U8aa9dM/s1600/Tarantino10colhans_1460858i.jpg", @"https://awestruckwanderer.files.wordpress.com/2014/02/alan-watts.png", @"https://www.esalen.org/sites/default/files/photo_images/20120201_DELLIS__MG_9612_711.jpg"]; for (NSSsortingng *image in images){ NSURL *myURL = [NSURL URLWithSsortingng:image]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:myURL]; NSLog(@"Can handle request %@", @([NSURLConnection canHandleRequest:request])); NSOperationQueue *queue = [[NSOperationQueue alloc]init]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { NSLog(@"In the completion handler"); if (!error) { // save data to cache with url as key NSLog(@"Image Added to Cache"); [myCache setObject:data forKey:myURL]; } else { NSLog(@"Image Not Added to Cache"); } }]; } } return 0; } 

Mon intuition est que la queue est désaffectée avant que la request soit terminée et que les cycles de retenue sont impliqués

Pas assez. Les cycles de retenue ne sont pas impliqués. La persistance est impliquée. Vous faites ceci dans une fonction main . Il se ferme immédiatement – le contenu asynchronous (le réseau et le callback subséquent) est asynchronous, donc il viendrait plus tard, si nous avions de la persistance. Mais nous ne le faisons pas. sorties main , et cela signifie que l' set du programme repris est détruit, kaboom , avant qu'il n'y ait une opportunité de faire du networking, et encore less de callbacker dans le gestionnaire d'achèvement après le networking.

Maintenant, comparez cela avec la façon dont les choses se passent dans la vraie vie. Dans une application iOS réelle, le main ne se termine pas , car il appelle UIApplicationMain , qui boucle jusqu'à ce que l'application soit terminée.

 int main(int argc, char *argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSSsortingngFromClass([AppDelegate class])); } } 

Dans ce code, UIApplicationMain continue de s'exécuter jusqu'à ce qu'il soit abandonné ou terminé. Pendant ce time, les classs et les instances ont vu le jour et elles persistent, car UIApplicationMain ne s'arrête pas. Par exemple:

 @implementation MyViewController - (void) someMethod { // ... [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { // ... } } @end 

Maintenant, dans un sens, exactement la même chose arrive: someMethod sort immédiatement. Mais notre programme global est toujours en cours! UIApplicationMain a une boucle d'exécution et cette boucle d'exécution est toujours en cours de cycle. Ainsi, les choses continuent de vivre, et maintenant le matériel asynchronous peut se produire – nous pouvons réseauter et ensuite appeler le callback.