3

У меня есть следующий код внутри класса (статический метод), который я вызываю для получения данных из API. Я решил сделать это статическим методом, чтобы я мог повторно использовать его в некоторых других частях приложения.AFNetworking: Обработка запроса асинхронного запроса с AFJSONRequestOperation

+ (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; 
} 

Теперь мой вопрос, когда я называю это в (метод ViewDidLoad) ViewController. Статический метод будет работать до конца и будет возвращать нуль в комнатах, но Nslog отобразит блок «Успех» Nslog через несколько секунд после. Теперь я понимаю, что это асинхронно, поэтому он не дождался выполнения блока успеха до того, как он достигнет «комнат возврата»; линия. Со всем сказанным мне нужен совет относительно того, как справиться с этим, например, индикатор прогресса или что-то в этом роде? Или что-то, что задерживает его? Я не совсем уверен, что это лучший способ, или если это так, я не знаю, как это сделать.

Любые советы очень ценятся. Спасибо!

+0

Поскольку «AFNetworking» является асинхронным процессом, вам рекомендуется использовать «NSNotificationCenter», который уведомит ваш код о том, что теперь у комнаты есть данные. –

+1

@DeepakKhiwani Правильно относится к асинхронности, но обмен сообщениями лучше всего делать непосредственно с блоками обратного вызова, а не с уведомлениями. – mattt

ответ

3

AFNetworking построен вокруг асинхронность-начиная запрос, а затем выполняет некоторую часть код после завершения этого запроса.

waitUntilFinished - это анти-шаблон, который может блокировать пользовательский интерфейс.

Вместо этого ваш метод не должен иметь тип возвращаемого (void), и есть параметр завершения блока, который возвращает сериализированную массив номеров:

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

Смотрите пример приложения в проекте AFNetworking для примера как это сделать.

+0

Значит ли это, что сделать статический метод (который возвращает массив комнат) - это не путь? Кажется, я не могу найти этот примерный проект, о котором вы говорите. – gdubs

+0

@gdubs Да. И [пример проекта находится в репозитории AFNetworking] (https://github.com/AFNetworking/AFNetworking/tree/master/Example). – mattt

+0

это сработало! Вы автор? Большое спасибо за ответ! Кстати, любой шанс, что вы знаете, как сделать эту работу с mbprogresshud вместо activityindicatorview? – gdubs

-1

Вы можете написать свой метод следующим образом:

+ (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]; 

} 

вы можете вызвать этот метод, как следующие:

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

не заставит его синхронизировать его? Я думал, что это не рекомендуется? – gdubs

+0

также, когда я называю этот метод, как я должен обрабатывать часть «roomArray»? NSArray * testrooms = [Room getAllRoomsWithEventId: eventId:^(NSArray ......); Кажется, мне нужно что-то добавить в этой части? – gdubs

+0

все не так. Вы передаете свой ответ через этот блок. Вы можете использовать NSNotification для обнаружения при завершении async. –

Смежные вопросы