How to use the Afnetworking 2.0 library synchronously?

Asked

Viewed 287 times

5

I would like to call a Rest service using the library AFNetworking.
How to make a call synchronously, ie wait for the return of the webservice?

For example:

Method that will return a car object:

Carro *carro = [self findCarroById:idCarro];
//restante do código... preciso ter a variável carro carregada antes de prosseguir.

Method that will be called:

- (Carro *)findCarroById:(NSString *)idCarro {

    NSString *url = [NSString stringWithFormat: @"%@%@", @"http://www.site.com/rest/carro/", idCarro];

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

    manager.responseSerializer = [AFJSONResponseSerializer serializer];

    [manager GET:url parameters:nil
         success:^(AFHTTPRequestOperation *operation, id json) {
            Carro *carro = [[Carro alloc] init];

            carro.idCarro = [json objectForKey:@"id"];
            carro.descricao = [json objectForKey:@"descricao"];

            //talvez poderia colocar o return aqui
         }
         failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"Erro: \n\n%@", error);
         }
     ];

    return carro;
}

2 answers

2


This is not the right way to proceed. As you are dealing with an HTTP call, you cannot assume that the application will wait for its termination.

Implementations in this way would block the user interface if used in the main thread (the Parenting app locked for the user), so the Afnetworking library doesn’t even bother to perform synchronous requests.

Assuming you’re loading the information from a car to be displayed on a screen in an iPhone app, what you should do is request the car information on - (void) viewDidLoad;, and present to the user a load indicator "Loading..." for example.

When the upload is finished, i.e., in the Success block, you should then change the views with the new data loaded. Follow an example:

- (void) viewDidLoad {
    // Solicita o carregamento do carro, porém não espera um retorno.
    [self loadCarWithId:carId];
    // Exibe indicador de progresso para o usuário.
    [ProgressHUD show:@"Loading..."];
}

- (void) loadCarWithId:(NSInteger)carId {
    NSString *url = [NSString stringWithFormat: @"%@%@", @"http://www.site.com/rest/carro/", carId];

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

    manager.responseSerializer = [AFJSONResponseSerializer serializer];

    [manager GET:url parameters:nil
         success:^(AFHTTPRequestOperation *operation, id json) {
            // Lida com os dados após o carregamento.
            Carro *carro = [[Carro alloc] init];
            carro.idCarro = [json objectForKey:@"id"];
            carro.descricao = [json objectForKey:@"descricao"];


            // Atualiza a tela com os dados do carro
            self.carIdLabel.text = carr.idCarro; // Assumindo que existe uma label "carIdLabel" na sua view.
            self.carDescriptionLabel.text = carro.descricao;  // Assumindo que existe uma label "carDescriptionLabel" na sua view.

            // Você também pode chamar um médoto quando esta requisição for concluída.
            [self saveCar:carro];
            // Remove o indicador de progresso pois o carregamento já foi concluído.
            [ProgressHUD dismiss];
         }
         failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"Erro: \n\n%@", error);
            // Remove o indicador de progresso pois o carregamento falhou.
            [ProgressHUD dismiss];
            // Avisa o usuário que o carregamento falhou ou tenta denovo.
         }
     ];

    // Não há retorno pois essa requisição é assíncrona.

}

// Isso só vai ser executado depois que a requisição for concluída
// já que está sendo chamado dentro do block de success.
- (void) saveCar:(Carro)carro {
    [[NSUserDefaults standartUserDefaults] setObject:carro forKey:@"savedCar"]; 
    //Isso é apenas um exemplo, não funciona pois o objeto Carro precisa ser desserializado para ser salvo no user defaults.
}

EDIT:

Added example of activity indicator through Progresshud: https://github.com/relatedcode/ProgressHUD

  • Thanks @Julio, in my case I will only use the ProgressHUD. Very good your explanation.

1

  • I had already looked at this tutorial, but it seems that they have been updating. Thanks for the tip!

  • Dude, I don’t know if you’ve solved your problem yet, but here’s another tutorial on the subject that might help: http://code.tutsplus.com/tutorials/working-with-nsurlsession-afnetworking-20-mobile-22651

Browser other questions tagged

You are not signed in. Login or sign up in order to post.