Question

I am trying to perform three different JSON connections to populate a mapView with markers form three different MySQL tables.

This is the code I have now to do it. To test the connections, I am logging the didReceiveData method, but the compiler cursor is not arriving at that method and, of course, any marker is shown on the map.

You are kindly requested to take a look at my code and tell me what am I missing or doing wrong. Thank you.

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.title = @"Geolocalización";


    //carga de datos JSON
    //network activity indicator showed during downloading data
    //PROCESSING FIRST CONNECTION
    first_connection_url = [NSURL URLWithString:@"http://mujercanariasigloxxi.appgestion.eu/app_php_files/empresastodaslist.php"];
    NSURLRequest *first_connection_request = [NSURLRequest requestWithURL:first_connection_url];
    NSURLConnection *first_connection=[[NSURLConnection alloc]initWithRequest:first_connection_request delegate:self];

    //PROCESSING SECOND CONNECTION
    second_connection_url = [NSURL URLWithString:@"http://mujercanariasigloxxi.appgestion.eu/app_php_files/centrostodoslist.php"];
    NSURLRequest *second_connection_request = [NSURLRequest requestWithURL:second_connection_url];
    NSURLConnection *second_connection=[[NSURLConnection alloc]initWithRequest:second_connection_request delegate:self];
    //PROCESSING THIRD CONNECTION
    third_connection_url = [NSURL URLWithString:@"http://mujercanariasigloxxi.appgestion.eu/app_php_files/eventostodoslist.php"];
    NSURLRequest *thrid_connection_request = [NSURLRequest requestWithURL:third_connection_url];
    NSURLConnection *third_connection=[[NSURLConnection alloc]initWithRequest:second_connection_request delegate:self];


}

//methods to perform the connection and population of data

-(void)connection: (NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    if(connection==first_connection){
        data_for_first_connection = [[NSMutableData alloc]init];

    }
    else if(connection==second_connection){
        data_for_second_connection = [[NSMutableData alloc]init];
    }
    else if(connection==third_connection){
        data_for_third_connection = [[NSMutableData alloc]init];
    }
}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)thedata
{
    if(connection==first_connection){
        [data_for_first_connection appendData:thedata];
        NSLog(@"CONEXION 1 AQUI");
    }
    else if(connection==second_connection){
        [data_for_second_connection appendData:thedata];
     NSLog(@"CONEXION 2 AQUI");
    }
    else if(connection==third_connection){
        [data_for_third_connection appendData:thedata];
     NSLog(@"CONEXION 3 AQUI");
    }
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    //if data received network indicator not visible
    [UIApplication sharedApplication].networkActivityIndicatorVisible=NO;

    if(connection==first_connection) {

        categorias_first = [NSJSONSerialization JSONObjectWithData:data_for_first_connection options:0 error:nil];

    }
    else if(connection==second_connection){

        categorias_second = [NSJSONSerialization JSONObjectWithData:data_for_second_connection options:0 error:nil];
    }
    else if(connection==third_connection){
        // PROCESS TO BE DONE FOR SECOND CONNECTION
        categorias_third = [NSJSONSerialization JSONObjectWithData:data_for_third_connection options:0 error:nil];
    }

    // Create a GMSCameraPosition that tells the map to display the
    // coordinate -33.86,151.20 at zoom level 6.
    GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:27.9847
                                                            longitude:-15.5953
                                                                 zoom:9];
    mapView_ = [GMSMapView mapWithFrame:CGRectZero camera:camera];
    mapView_.myLocationEnabled = YES;
     mapView_.delegate = self;
    self.view = mapView_;

    UISegmentedControl *mainSegment = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"Ofertas", @"Cursos", @"Eventos", nil]];
    [mainSegment setSegmentedControlStyle:UISegmentedControlStyleBar];
    mainSegment.frame = CGRectMake(20,80, 280, 43);
    //self.navigationItem.titleView = mainSegment;
    //mainSegment.selectedSegmentIndex = nil;
    [mainSegment addTarget:self action:@selector(mainSegmentControl:) forControlEvents: UIControlEventValueChanged];
    [self.view addSubview:mainSegment];


}

UPDATED CODE FOR TESTING THE APP.

I have updated my code to test it, now I am only working with two connections. At logging the results, I detect that arrays categoria (at first_connection) and categoria2 (at second_connection) are populated from the same JSON file (from first_connection):

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.title = @"Geolocalización";



    //carga de datos JSON
    //network activity indicator showed during downloading data
    [UIApplication sharedApplication].networkActivityIndicatorVisible=YES;

    //URL definition where php file is hosted
    //conexion1
    url = [NSURL URLWithString:@"http://mujercanariasigloxxi.appgestion.eu/app_php_files/empresastodaslist.php"];

    request = [NSURLRequest requestWithURL:url];

    first_connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];


    //conexion2
    url2 = [NSURL URLWithString:@"http://mujercanariasigloxxi.appgestion.eu/app_php_files/centrostodoslist.php"];

    request2 = [NSURLRequest requestWithURL:url];

    second_connection = [[NSURLConnection alloc] initWithRequest:request2 delegate:self];






}

//methods to perform the connection and population of data

-(void)connection: (NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{

    if ([connection isEqual:first_connection]){
        NSLog(@"FIRST CONNECTION RESPONSE");
        data = [[NSMutableData alloc]init];
    }

    if ([connection isEqual:second_connection]){
        NSLog(@"SECOND CONNECTION RESPONSE");
        data2 = [[NSMutableData alloc]init];
    }


    NSLog(@"ESTOY EN DIDRECEIVERESPONSE");
}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)thedata
{


    if ([connection isEqual:first_connection]){
        NSLog(@"FIRST CONNECTION RECEIVED");
       [data appendData:thedata];

    }
    if ([connection isEqual:second_connection]){
        NSLog(@"SECOND CONNECTION RECEIVED");
        [data2 appendData:thedata];

    }




}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    //if data received network indicator not visible
    [UIApplication sharedApplication].networkActivityIndicatorVisible=NO;

    //array waterfalls populated via JSON from database

    if ([connection isEqual:first_connection]){
    categorias = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        NSLog(@"DATA1 = %@",categorias);
    }
    if ([connection isEqual:second_connection]){
    categorias2 = [NSJSONSerialization JSONObjectWithData:data2 options:0 error:nil];
        NSLog(@"DATA2 = %@",categorias2);
    }
    NSLog(@"NUMERO DE EMPRESAS OPCION1= %lu"
          , (unsigned long)[categorias count]);
    NSLog(@"NUMERO DE EMPRESAS OPCION2= %lu"
          , (unsigned long)[categorias2 count]);
    // Create a GMSCameraPosition that tells the map to display the
    // coordinate -33.86,151.20 at zoom level 6.
    GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:27.9847
                                                            longitude:-15.5953
                                                                 zoom:9];
    mapView_ = [GMSMapView mapWithFrame:CGRectZero camera:camera];
    mapView_.myLocationEnabled = YES;
     mapView_.delegate = self;
    self.view = mapView_;




    UISegmentedControl *mainSegment = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"Ofertas", @"Cursos", @"Eventos", nil]];
    [mainSegment setSegmentedControlStyle:UISegmentedControlStyleBar];
    mainSegment.frame = CGRectMake(20,80, 280, 43);
    //self.navigationItem.titleView = mainSegment;
    //mainSegment.selectedSegmentIndex = nil;
    [mainSegment addTarget:self action:@selector(mainSegmentControl:) forControlEvents: UIControlEventValueChanged];
    [self.view addSubview:mainSegment];


}
Was it helpful?

Solution

I see a couple of problems. For one, your connections, firstConnection, secondConnection, etc, are created as local variables, so they will be deallocated as soon as viewDidLoad goes out of scope. When you check for equality in the delegate methods, they will be nil at that point. You should create ivars or properties for those connections. Additionally, you shouldn't use "==" to compare objects, use isEqual: instead.

else if([connection isEqual:third_connection]){

OTHER TIPS

The immediate problem, as rdelmar pointed out, is that you're not saving the NSURLConnection references in the ivars that you refer to later. That's the first thing to fix.

The broader problem is more fundamental. You're starting three connections, but your connectionDidFinishLoading seems to not recognize that fact it will get called three times, once for each connection. Notably the latter part of that routine, which is creating the map view and the segment control, will be performed once for each of the three JSON download requests. Surely you meant to do that UI-related stuff only once, when all three connections were done.

The elegant approach would be to wrap these individual network requests in NSOperation objects and use operation queue to manage the "completion logic" which would include the UI stuff. You could implement this with AFNetworking, or wrap the NSURLConnection in your own NSOperation subclass. Then you could add these three operations, but have a final completion operation, dependent upon the completion of the other three download operations, which would update the UI.

A simpler fix to your existing code would be to add three boolean ivars, indicating whether the three individual downloads were done. Then your connectionDidFinishLoading, as it's called each time for the three download requests, could update the respective boolean for each. And it would then only perform the UI related stuff if all three were done.

You are not calling "start" for your connections.

1) To keep your code, you need to call "start" for each connection, after initWithRequest:;
For example, [first_connection start];

2) If all you need (and this seems to be the case) is to do an http get and get the NSData response, you can simply do NSData *jsonData = [NSData dataWithContentsOfUrl:[NSURL urlWithString:@"http://mujercanariasigloxxi.appgestion.eu/app_php_files/empresastodaslist.php"]];

3) If you need it to happen in a separate thread, you can call dataWithContentsOfUrl inside a block like this:

<pre>
- (void) getJsonData
{
    //main thread
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
   ^{
       //background thread
       NSData *jsonData = [NSData dataWithContentsOfUrl:[NSURL urlWithString:@"http://mujercanariasigloxxi.appgestion.eu/app_php_files/empresastodaslist.php"]];
       dispatch_async(dispatch_get_main_queue(),
      ^{
          //main thread again

          //parse json and add pins
      });
   });
}
</pre>

Good luck!

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