0

I need to pass 2 NSDictionary from a ViewController to another ViewController, My App some times pass the data ok, but, another times, data don't reach to second ViewController.

I need consult a web service twice, that web service response is a JSON, this JSON (2) is what I need pass to other ViewController

The call to web service is made here (in dispatch_async):

double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delayInSeconds * NSEC_PER_SEC));
dispatch_queue_t queue = dispatch_queue_create("com.micrologica.modules", nil);

dispatch_async(queue, ^{
    urlConsultarDisponibilidad = [NSString stringWithFormat:connectionUrl getAvailableModuleListAPI, fechaDiaUno, idLocal, idServicioUno, idProfesionalUno, idServicioDos, idProfesionalDos];
    [FunctionsAmano setConnectionAndRequest:urlConsultarDisponibilidad completion:^(NSDictionary *dataResponse) {
        NSLog(@"response dia 1: %@", dataResponse);
        if(dataResponse) {
            NSString *resp = [NSString stringWithFormat:@"%@", [dataResponse objectForKey:@"resp"]];
            if([resp isEqualToString:@"1"]) {
                NSLog(@"almost finish 1");
                modulesDiaUno = [dataResponse objectForKey:@"data"];
            }

            dispatch_after(popTime, queue, ^(void){
                finishedDiaUno = YES;
                NSLog(@"finished 1");
            });
        }
    }];
});

dispatch_async(queue, ^{
    urlConsultarDisponibilidad = [NSString stringWithFormat:connectionUrl getAvailableModuleListAPI, fechaDiaDos, idLocal, idServicioUno, idProfesionalUno, idServicioDos, idProfesionalDos];
    [FunctionsAmano setConnectionAndRequest:urlConsultarDisponibilidad completion:^(NSDictionary *dataResponse) {
        NSLog(@"response dia 2: %@", dataResponse);
        if(dataResponse) {
            NSString *resp = [NSString stringWithFormat:@"%@", [dataResponse objectForKey:@"resp"]];
            if([resp isEqualToString:@"1"]) {
                NSLog(@"almost finish 2");
                modulesDiaDos = [dataResponse objectForKey:@"data"];
            }

            dispatch_after(popTime, queue, ^(void){
                finishedDiaDos = YES;
                NSLog(@"finished 2");
            });
        }
    }];
});

dispatch_async(queue, ^{
    dispatch_async(dispatch_get_main_queue(), ^{
        BOOL exito = YES;
        int segundos = 0;
        /* Si la consulta se demora mas de 60 segundos, se interrumpe e informa al usuario de un problema */
        while (!finishedDiaUno && !finishedDiaDos) {
            [NSThread sleepForTimeInterval:1];
            if(segundos >= 60) {
                exito = NO;
                break;
            }
            segundos++;
        }

        if(exito) {
            HorariosViewController *horariosView = [self.storyboard instantiateViewControllerWithIdentifier:@"ModulesView"];
            horariosView.modulesDiaUno = self.modulesDiaUno;
            horariosView.modulesDiaDos = self.modulesDiaDos;

            double delayInSeconds = 4.0;
            dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delayInSeconds * NSEC_PER_SEC));
            dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
              [self presentViewController:horariosView animated:NO completion:nil];
            });
        }
    });
});

This code is working fine, but, some times the response (dataResponse) comes after I make change of ViewController, I don't know why changes ViewController if the dataResponse not came.

How to you see, I instantiate of the second ViewController, I set the data, and change the ViewController on a dispatch_after (4.0 seconds). Why I change the ViewController in a dispatch_after? because, if I don't implement the dispatch_after, the NSDictionarys ALWAYS comes empty!, In this way, the NSDictionarys some times comes empty and some times comes ok.

Can you tell me why is wrong with my code?

PS: the dictionaries appear empties in the other ViewController (has no element, but is not null).

AUbilla
  • 19
  • 6
  • What does "empty" means ? `horariosView.modulesDiaUno` exists but has not element or it is nil. – KudoCC Mar 28 '14 at 01:08
  • Hello KudoCC, I suplemented the info with other piece of code. Thanks! – AUbilla Mar 28 '14 at 01:49
  • possible duplicate of [Passing Data between View Controllers](http://stackoverflow.com/questions/5210535/passing-data-between-view-controllers) – Hot Licks Mar 28 '14 at 01:55

1 Answers1

0

Here is a advice: don't block your main thread, don't call sleep on main thread.

It a concurrency problem , the method setConnectionAndRequest:urlConsultarDisponibilidad should be asynchronous and the UI code may execute before the two responses. I think it can be fixed like this:

double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delayInSeconds * NSEC_PER_SEC));
dispatch_queue_t queue = dispatch_queue_create("com.micrologica.modules", nil);

dispatch_async(queue, ^{
    urlConsultarDisponibilidad = [NSString stringWithFormat:connectionUrl getAvailableModuleListAPI, fechaDiaUno, idLocal, idServicioUno, idProfesionalUno, idServicioDos, idProfesionalDos];
    [FunctionsAmano setConnectionAndRequest:urlConsultarDisponibilidad completion:^(NSDictionary *dataResponse) {
        NSLog(@"response dia 1: %@", dataResponse);
        if(dataResponse) {
            NSString *resp = [NSString stringWithFormat:@"%@", [dataResponse objectForKey:@"resp"]];
            if([resp isEqualToString:@"1"]) {
                NSLog(@"almost finish 1");
                modulesDiaUno = [dataResponse objectForKey:@"data"];
            }

            dispatch_after(popTime, queue, ^(void){
                finishedDiaUno = YES;
                NSLog(@"finished 1");

                if (finishedDiaDos) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        HorariosViewController *horariosView = [self.storyboard instantiateViewControllerWithIdentifier:@"ModulesView"];
                        horariosView.modulesDiaUno = self.modulesDiaUno;
                        horariosView.modulesDiaDos = self.modulesDiaDos;
                        [self presentViewController:horariosView animated:NO completion:nil];
                    });
                }
            });
        }
    }];
});

dispatch_async(queue, ^{
    urlConsultarDisponibilidad = [NSString stringWithFormat:connectionUrl getAvailableModuleListAPI, fechaDiaDos, idLocal, idServicioUno, idProfesionalUno, idServicioDos, idProfesionalDos];
    [FunctionsAmano setConnectionAndRequest:urlConsultarDisponibilidad completion:^(NSDictionary *dataResponse) {
        NSLog(@"response dia 2: %@", dataResponse);
        if(dataResponse) {
            NSString *resp = [NSString stringWithFormat:@"%@", [dataResponse objectForKey:@"resp"]];
            if([resp isEqualToString:@"1"]) {
                NSLog(@"almost finish 2");
                modulesDiaDos = [dataResponse objectForKey:@"data"];
            }

            dispatch_after(popTime, queue, ^(void){
                finishedDiaDos = YES;
                NSLog(@"finished 2");

                if (finishedDiaUno) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        HorariosViewController *horariosView = [self.storyboard instantiateViewControllerWithIdentifier:@"ModulesView"];
                        horariosView.modulesDiaUno = self.modulesDiaUno;
                        horariosView.modulesDiaDos = self.modulesDiaDos;
                        [self presentViewController:horariosView animated:NO completion:nil];
                    });
                }
            });
        }
    }];
});
KudoCC
  • 6,912
  • 1
  • 24
  • 53
  • I'm testing your code, this appears to work, but I have a question, in your code, I'm calling twice to change of ViewController? Once when finishDiaUno is YES, and once more when finishedDiaDos is YES?, this affects on something? – AUbilla Mar 28 '14 at 02:12
  • It won't call twice because the queue is serial, if the first response come first, the `finishedDiaUno` will be set to YES first but `finishedDiaDos` is NO, so the ViewController won't be presented, then the second response comes, both finishedDiaUno and finishedDiaDos is YES, the viewcontroller will be presented. – KudoCC Mar 28 '14 at 02:17
  • Awesome! thank you very much!, I did tested 40 times and don't fails any!!! before you help me, my code failed on 4 o 5 times! Thank you very much! – AUbilla Mar 28 '14 at 02:48
  • Suggest reading this:[Concurrency Programming Guide](https://developer.apple.com/library/ios/documentation/general/conceptual/concurrencyprogrammingguide/Introduction/Introduction.html) – KudoCC Mar 28 '14 at 02:54
  • Thanks, I know I need read about programming on IOS, I only have been 2 weeks programming in IOS, but with this problem resolved, the App is done!, then now I have time to read and study :) – AUbilla Mar 28 '14 at 03:07