AFNetworking: event handling request get asíncrona con AFJSONRequestOperation

Tengo el siguiente código dentro de una class (método estático) al que llamo para get datos de una API. Decidí hacer de esto un método estático solo para poder reutilizarlo en otras partes de la aplicación.

+ (NSArray*) getAllRoomsWithEventId:(NSNumber *)eventId{ NSURL *urlRequest = [NSURL URLWithString:[NSString stringWithFormat:@"http://blablba.com/api/Rooms/GetAll/e/%@/r?%@", eventId, [ServiceRequest getAuth]]]; NSMutableArray *rooms = [[NSMutableArray alloc] init]; NSURLRequest *request = [NSURLRequest requestWithURL:urlRequest]; AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { NSLog(@"Response of getall rooms %@", JSON); NSArray *jsonResults = (NSArray*)JSON; for(id item in jsonResults){ Room* room = [[Room alloc]init]; if([item isKindOfClass:[NSDictionary class]]){ room.Id = [item objectForKey:@"Id"]; room.eventId = [item objectForKey:@"EventId"]; room.UINumber = [item objectForKey:@"RoomUIID"]; [rooms addObject:room]; } } } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON){ NSLog(@"Error"); }]; [operation start]; [operation waitUntilFinished]; return rooms; } 

Ahora mi problema es que siempre que lo llamo en un ViewController (método ViewDidLoad). El método estático se ejecutará hasta el final y devolverá nulos en las habitaciones, pero el Nslog mostrará el bloque "Success" Nslog unos segundos después. Ahora entiendo que esto es asíncrono, así que no espera a que se ejecute el bloque de éxito antes de que llegue a las "salas de retorno"; línea. Con todo eso dicho, necesito algunos consejos sobre cómo manejar esto, como tal vez una barra de progreso o algo así? ¿O algo que lo retrasa? No estoy realmente seguro si esa es la forma correcta o si es así, no estoy seguro de cómo hacerlo.

Cualquier consejo es muy apreciado. ¡Gracias!

AFNetworking se basa en la asynchronization: inicia una request y luego ejecuta una pieza de código una vez que la request ha finalizado.

waitUntilFinished es un anti-patrón, que puede bloquear la interfaz de usuario.

En su lugar, su método no debe tener ningún tipo de retorno (void) y tener un parámetro de bloque de finalización que devuelva la serie serializada de habitaciones:

- (void)allRoomsWithEventId:(NSNumber *)eventId block:(void (^)(NSArray *rooms))block { // ... }

Vea la aplicación de ejemplo en el proyecto AFNetworking para ver un ejemplo de cómo hacerlo.

Puedes escribir tu método de la siguiente manera:

 + (void) getAllRoomsWithEventId:(NSNumber *)eventId:(void(^)(NSArray *roomArray)) block { NSURL *urlRequest = [NSURL URLWithString:[NSString stringWithFormat:@"http://blablba.com/api/Rooms/GetAll/e/%@/r?%@", eventId, [ServiceRequest getAuth]]]; NSMutableArray *rooms = [[NSMutableArray alloc] init]; NSURLRequest *request = [NSURLRequest requestWithURL:urlRequest]; AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { NSLog(@"Response of getall rooms %@", JSON); NSArray *jsonResults = (NSArray*)JSON; for(id item in jsonResults){ Room* room = [[Room alloc]init]; if([item isKindOfClass:[NSDictionary class]]){ room.Id = [item objectForKey:@"Id"]; room.eventId = [item objectForKey:@"EventId"]; room.UINumber = [item objectForKey:@"RoomUIID"]; [rooms addObject:room]; } } block(rooms); } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON){ NSLog(@"Error"); block(nil); //or any other error message.. }]; [operation start]; [operation waitUntilFinished]; } 

Puedes llamar a este método de la siguiente manera:

 [MyDataClass getAllRoomsWithEventId:@"eventid1":^(NSArray *roomArray) { NSLog(@"roomArr == %@",roomArray); }];