Question

I'm new to iOS and I have trouble understanding and applying well dispatch ... I have an application I need to query a website (api) within a for loop, the end of that cycle I need to make further inquiries in another cycle, and finally, at the end of both cycles need to switch views.

I now have this code (after much trial and error but still does not work):

dispatch_queue_t queue = dispatch_queue_create("threadServicios", DISPATCH_QUEUE_SERIAL);

    dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);

    dispatch_async(queue, ^(void) {
        NSLog(@"llego a buscar servicios por local");
        for (NSDictionary *local in _arrLocalesTmp) {
            [self getListaServiciosPorLocal:[local objectForKey:@"idLocal"]];
            //this function calls another function that consumes a web service and get a json
        }

        procced = YES;

        NSLog(@"llego a buscar profesionales por local");
        for (NSDictionary *local in _arrLocalesTmp) {
            [self getListaProfesionalesPorLocal:[local objectForKey:@"idLocal"]];
            //this function calls another function that consumes a web service and get a json
        }

        procced2 = YES;

        dispatch_group_leave(group);
    });

    dispatch_group_notify(group, dispatch_get_main_queue(),^{
        NSLog(@"dispatch procced 1");
        if (procced && procced2) {
            [self setFormularioConsultaCompleto];
        }
    });

The function [self getListaServiciosPorLocal: [Local objectForKey: @ "idLocal"]]; is as follows:

dispatch_async(dispatch_get_main_queue(), ^(void) {
    NSURL *url = [NSURL URLWithString:urlConnection];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    sessionConfiguration.timeoutIntervalForRequest = 30;
    sessionConfiguration.timeoutIntervalForResource = 60;

    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        __block NSError *jsonError;
        NSHTTPURLResponse *urlResponse = (NSHTTPURLResponse *) response;

        if(!error) {
            if(urlResponse.statusCode == 200) {
                NSDictionary *response = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&jsonError];

                if(response) {
                NSString *resp = [NSString stringWithFormat:@"%@", [dataResponse objectForKey:@"resp"]];
                if([resp isEqualToString:@"1"]) {
                    _json = [dataResponse objectForKey:@"data"];
                    [_arrServiciosTmp addObjectsFromArray:(NSArray *)_json];
                } else {
                    NSString *message = [dataResponse objectForKey:@"description"];
                }
            } else {
                self.lblMensaje.text = @"Ha ocurrido un error al obtener la información, por favor, vuelva a intentarlo en unos momentos.";
            }
            } else {
                completion(nil);
            }
        } else {
            NSLog(@"Error en Task");
        }                            
    });

And the function [self getListaProfesionalesPorLocal: [Local objectForKey: @ "idLocal"]]; is similar but obtains other information

The problem is that the app calls this function [self setFormularioConsultaCompleto]; (changing the view) but the above functions still do not quite get all the data from webservice.

Sorry for this, but I gave up, I hope can help me!

Thanks!

Was it helpful?

Solution

The below uses dispatch groups to hold off starting another block till the groups work has been completed.

First change your data methods to not be wrapped in dispatch_async and accept a completion block, calling that at the end of the NSURLSessionDataTasks completionHandler:

-(void)getListaServiciosPorLocal:(id)whatEver withCompletionBlock:(dispatch_block_t)block
{
    NSURL *url = [NSURL URLWithString:urlConnection];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    sessionConfiguration.timeoutIntervalForRequest = 30;
    sessionConfiguration.timeoutIntervalForResource = 60;

    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        __block NSError *jsonError;
        NSHTTPURLResponse *urlResponse = (NSHTTPURLResponse *) response;

        if(!error) {
            if(urlResponse.statusCode == 200) {
                NSDictionary *response = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&jsonError];

                if(response) {
                    NSString *resp = [NSString stringWithFormat:@"%@", [dataResponse objectForKey:@"resp"]];
                    if([resp isEqualToString:@"1"]) {
                        _json = [dataResponse objectForKey:@"data"];
                        [_arrServiciosTmp addObjectsFromArray:(NSArray *)_json];
                    } else {
                        NSString *message = [dataResponse objectForKey:@"description"];
                    }
                } else {
                    self.lblMensaje.text = @"Ha ocurrido un error al obtener la información, por favor, vuelva a intentarlo en unos momentos.";
                }
            } else {
                completion(nil);
            }
        } else {
            NSLog(@"Error en Task");
        }  
        block();  // Notify completion block                        
    });
}

Now when you call these methods:

dispatch_group_t group = dispatch_group_create();

dispatch_async(queue, ^(void) {

    NSLog(@"llego a buscar servicios por local");
    for (NSDictionary *local in _arrLocalesTmp) {
        dispatch_group_enter(group);
        [self getListaServiciosPorLocal:[local objectForKey:@"idLocal"] withCompletionBlock:^{
            dispatch_group_leave(group);
        }];
    }

    NSLog(@"llego a buscar profesionales por local");
    for (NSDictionary *local in _arrLocalesTmp) {
        dispatch_group_enter(group);
        [self getListaProfesionalesPorLocal:[local objectForKey:@"idLocal"] withCompletionBlock:^{
            dispatch_group_leave(group);
        }];
    }
});    

dispatch_group_notify(group, dispatch_get_main_queue(),^{

    [self setFormularioConsultaCompleto];
});

(Adapted from this answer)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top