AFNetworking y NSURLConnection en el hilo principal

introduzca la descripción de la imagen aquí

EDITAR: La fila resaltada en la captura de pantalla es con lo que tengo un problema, ¿por qué NSURLConnection está ejecutando en [NSThread main] cuando no estoy llamándolo, AFNetworking es?

Estoy usando AFNetworking para mi proyecto, pero cuando ejecuto Time Profiler en Instruments veo mucha actividad en el hilo principal para NSURLConnection, tengo la sensación de que esto no es lo que quiero.

Mi método es

 - (void)parseArticles { NSMutableArray *itemsToParse = [[FMDBDataAccess shanetworkingDatabase] getItemsToParse]; NSMutableArray *operations = [[NSMutableArray alloc] init]; for (Post *p in itemsToParse) { NSMutableString *strURL = [NSMutableString new]; [strURL appendString:@"http://xxxxxxxxxxxxxxxxxxxxxx.php?url="]; [strURL appendString:[p href]]; NSURL *url = [NSURL URLWithString:strURL]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; [[ParserClient shanetworkingInstance] registerHTTPOperationClass:[AFHTTPRequestOperation class]]; [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { dispatch_async(loginParseQueue, ^{ Parser *parse = [[Parser alloc] init]; [parse parseLink:responseObject rowID:[p rowID]]; }); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"%@",error); }]; [operations addObject:operation]; } NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; [operationQueue setMaxConcurrentOperationCount:3]; [operationQueue addOperations:operations waitUntilFinished:NO]; } 

¿Por qué utilizar AFNetworking el hilo principal? y como lo soluciono

AFNetworking se ejecuta en un subprocess secundario no en el subprocess principal, pero cada subprocess tiene un método principal, que se encuentra en la image que publica. Este no es el tema principal. Ahora dime ¿Qué quieres solucionar?

Es porque AFNetworking usa "successCallbackQueue" para enrutar el bloque de finalización:

AFHTTPRequestOperation.m:

 self.completionBlock = ^{ if (self.error) { if (failure) { dispatch_async(self.failureCallbackQueue ?: dispatch_get_main_queue(), ^{ failure(self, self.error); }); } } else { if (success) { dispatch_async(self.successCallbackQueue ?: dispatch_get_main_queue(), ^{ success(self, self.responseData); }); } } }; 

Simplemente puede asignar un subprocess diferente a los bloques de finalización de éxito y falla:

 dispatch_queue_t backgroundQueue = dispatch_queue_create("com.name.bgqueue", NULL); AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; operation.successCallbackQueue = backgroundQueue; operation.failureCallbackQueue = backgroundQueue; 

EDITAR:

Aquí hay un código para ejecutar operaciones en un hilo de background. El uso de cualquier function llamada desde el subprocess de interfaz de usuario se ejecutará en el subprocess de interfaz de usuario. Puede usar una técnica similar a la especificada a continuación para ejecutar su operación en un hilo de background, y luego enviar el resultado de vuelta al hilo de la interfaz de usuario para su uso posterior.

Aquí está la técnica que usé, puede replace mi llamada sendSynchronousRequest con su AFHTTPRequestOperation :

Especifique un tipo especial (un bloque) para que pueda pasar bloques de código.

 typedef void (^NetworkingBlock)(NSString* stringOut); 

Luego, debe enviar a un subprocess de background, para no congelar su subprocess de interfaz de usuario.

Aquí hay una function para llamar a cosas en un hilo de background, y luego esperar una respuesta, y luego llamar a un bloque cuando haya terminado sin usar el hilo de la interfaz de usuario para hacerlo:

 - (void) sendString:(NSString*)stringIn url:(NSString*)url method:(NSString*)method completion:(NetworkingBlock)completion { //build up a request. NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]]; NSData *postData = [stringIn dataUsingEncoding:NSUTF8StringEncoding]; [request setHTTPMethod:method]; [request setValue:[NSString stringWithFormat:@"%d", postData.length] forHTTPHeaderField:@"Content-Length"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; //or whatever [request setHTTPBody:postData]; //dispatch a block to a background thread using GCD (grand central dispatch) dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSURLResponse *response; NSError* error; //request is sent synchronously here, but doesn't block UI thread because it is dispatched to another thread. NSData* responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; //call complete, so now handle the completion block. if (completion) { //dispatch back to the UI thread again dispatch_async(dispatch_get_main_queue(), ^{ if (responseData == nil) { //no response data, so pass nil to the stringOut so you know there was an error. completion(nil); } else { //response received, get the content. NSString *content = [[NSString alloc] initWithBytes:[responseData bytes] length:responseData.length encoding:NSUTF8StringEncoding]; NSLog(@"String received: %@", content); //call your completion handler with the result of your call. completion(content); } }); } }); } 

Úselo de esta manera:

 - (void) myFunction { [self sendString:@"some text in the body" url:@"http://website.com" method:@"POST" completion:^(NSString *stringOut) { //stringOut is the text i got back }]; }