AFNetworking: обработка асинхронного запроса на получение с помощью AFJSONRequestOperation

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

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

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

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

2 ответа

Решение

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

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

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

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

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

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

+ (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);
    }];
Другие вопросы по тегам