iosobjective-cjsonuitableviewgoogle-places-api

Sending API Data to UITableView Within ViewController


Having trouble filling a TableView within a ViewController (not a TableViewController) with data from the Google Places API.

I'm already pulling data successfully and parsing the JSON to a MKMapView with annotations, so I know that part's working, but I want the data to also flow into the table below it (see photo).

Example layout of MapView with TableView below

I've looked everywhere for a simple explanation of how to do this. Even followed a tutorial (but it was meant for a TableViewController, so I'm hoping my issue is just the way I've linked it). Another possibility is the placement of my [self.tableView reloadData]; call. It made logical sense to me, but could very well be in the wrong place. Apparently the TableView will remain blank if that's not in the right spot, but I've tried it in several places.

Note: I've only included the pertaining code to make it easier for readers to spot. The TableView object is connected to the ViewController as its data source and delegate, the prototype cell is called "Cell" in the Attribute Editor as called in the #pragma code, and the JSON data is being stored in an NSArray called "places". What have I missed?

ViewController.h

@interface RendezvousViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>

@property (strong, nonatomic)          NSArray *places;
@property (strong, nonatomic) IBOutlet UITableView *tableView;

ViewController.m

    -(void)viewDidLoad {
        self.tableView.dataSource = self;
        self.tableView.delegate = self;
}    
    
    -(void) queryGooglePlaces: (NSString *) googleType {
            // Build the url string to send to Google.
            NSString *url = [NSString stringWithFormat:@"https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=%f,%f&radius=%@&types=food|restaurant|bar&sensor=true&keyword=%@&key=%@",currentCentre.latitude,currentC

entre.longitude,[NSString stringWithFormat:@"%i",currenDist],selection, kGOOGLE_API_KEY];
        url = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        
        NSLog(@"%@", url);
        
        //Formulate the string as a URL object.
        NSURL *googleRequestURL=[NSURL URLWithString:url];
        
        // Retrieve the results of the URL.
        dispatch_async(kBgQueue, ^{
            NSData* data = [NSData dataWithContentsOfURL: googleRequestURL];
            [self performSelectorOnMainThread:@selector(fetchedData:) withObject:data waitUntilDone:YES];
        
        });
    }
        
        -(void)fetchedData:(NSData *)responseData {
            //parse out the json data
            NSError* error;
            NSDictionary* json = [NSJSONSerialization
                                  JSONObjectWithData:responseData
                                  
                                  options:kNilOptions
                                  error:&error];
            
            //The results from Google will be an array obtained from the NSDictionary object with the key "results".
            NSArray* places = [json objectForKey:@"results"];
            
            //Write out the data to the console.
            NSLog(@"Google Data: %@", places);
            
            [self plotPositions:places];
            [self.tableView reloadData];
        }
    
    #pragma mark - Table view data source
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        // Return the number of sections.
        return 1;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        // Return the number of rows in the section.
        return [self.places count];
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *CellIdentifier = @"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
        
        NSDictionary *tempDictionary= [self.places objectAtIndex:indexPath.row];
        
        cell.textLabel.text = [tempDictionary objectForKey:@"name"];
        
        if([tempDictionary objectForKey:@"rating"] != NULL)
        {
            cell.detailTextLabel.text = [NSString stringWithFormat:@"Rating: %@ of 5",[tempDictionary   objectForKey:@"rating"]];
        }
        else
        {
            cell.detailTextLabel.text = [NSString stringWithFormat:@"Not Rated"];
        }
        
        return cell;
    }

Solution

  • Looks like your dispatch_async call got some problem.

    Now Once you get the data, you should populate it from within the mainThread.

    You must modify your call as :

    dispatch_async(kBgQueue, ^{
        NSData* data = [NSData dataWithContentsOfURL: googleRequestURL];
        dispatch_sync(dispatch_get_main_queue(), ^{
            [self fetchedData:data];
        });
    });
    

    This will ensure that [self fetchedData:data]; is called only when you are done with load data from google in background thread.

    Here is similar result from my live example.

    enter image description here

    Also there's a bug in the code: Change this NSArray* places = [json objectForKey:@"results"]; to self.places = [json objectForKey:@"results"];.

    Hope that helps.