iOS (Parse.com) Loading PFObjects into Array?

Danneman101

macrumors 6502
Original poster
Aug 14, 2008
361
1
I'm using Parse.com's solution for databases, and want to load db-table into a UITable. I'm trying to accomplish this by first creating an array, then loading the database-table into that array, and finally loading the array into the UITable.

Code:
- (void)setupArray
{
    dummyArray = [[NSMutableArray alloc] init];

    PFQuery *query = [PFQuery queryWithClassName:@"Events"];
    [query findObjectsInBackgroundWithBlock:^(NSArray *comments, NSError *error) {
        for (PFObject *comment in comments) 
        {
            PFObject *post = [comment objectForKey:@"event"];            
            [dummyArray addObject:post];
        }
    }];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    
    cell.textLabel.text = [dummyArray objectAtIndex:indexPath.row];
    
    return cell;
}
However, nothing is shown in the UITable.

Could this be because the database does not have time to be retrieved before the "cellForRowAtIndexPath" is called (and thus is empty when cycling trough and setting up each cell)?

Or is my syntax wrong?

Alternatively, is there a better way of doing this?
 

Danneman101

macrumors 6502
Original poster
Aug 14, 2008
361
1
Yes, it was simply too slow to load. Instead I loaded the array in the AppDelegate immediately when the app was loaded, and then accessed it from the tableview-code.

Code:
    // Get:     AppDelegate
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    
    // Set:     Cell from AppDel>dummyArray
    cell.textLabel.text = [appDelegate.dummyArray objectAtIndex:indexPath.row];
 
Last edited:

jamesjyu

macrumors newbie
Feb 3, 2012
1
0
James here from Parse.

You were actually on the right track in your first example. The reason your table isn't showing any data is because setupArray is firing off an async request to get the objects and load the array. However, the UITableView is reading the array before the the callback from Parse is executed.

The right way to do this is to call reloadData on the table in the PFQuery block.

Hope this helps!
 

Danneman101

macrumors 6502
Original poster
Aug 14, 2008
361
1
James here from Parse.

You were actually on the right track in your first example. The reason your table isn't showing any data is because setupArray is firing off an async request to get the objects and load the array. However, the UITableView is reading the array before the the callback from Parse is executed.

The right way to do this is to call reloadData on the table in the PFQuery block.

Hope this helps!
Thanks for the reply! Yes, that was how I had already solved it :)

Function in AppDelegate:
Code:
- (void)setupArray
{
    // Set:     Bool (stops other calls being made to this function while it's running)
    B_setupArrayIsRunning = YES;
    
    // Init:    Array to hold the data retrieved
    eventArray          = [[NSMutableArray alloc] init];

    // Get:     DB from Parse.com
    PFQuery *query = [PFQuery queryWithClassName:str_ParseTableName];       // Get:     Class name from Parse.com
    [query orderByDescending:@"createdAt"];                                 // Order:   By most recent
    query.limit = [NSNumber numberWithInt:n_MaxNrEvents];                   // Get:     Only 10 most recent
    __block int counter = 0;
    [query findObjectsInBackgroundWithBlock:^(NSArray *comments, NSError *error) 
    {
        for (PFObject *comment in comments) 
        {           
            // Event
            PFObject *post = [comment objectForKey:@"event"];               // Get:     From Column "event"
            if (post == nil) { post = @" "; }                 // Save:    Empty string if no data in current tablerow
            [eventArray insertObject:post atIndex:counter];                 // Save:    DB-data to array
            
            counter ++;
        }
        
        // Lets AppDel access SecondViewController where the table is (this app uses storyboard and is a tabbarapplication)
        UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;            // GET: TabBarCtrl ->
        UINavigationController *navigationController = [[tabBarController viewControllers] objectAtIndex:1];    // GET: Second NavCtrl ->
        SecondViewController *secondVC = [[navigationController viewControllers] objectAtIndex:0];              // GET: SecondVC 

        // Reload:      Tableview
        [secondVC.myTableView reloadData];
        
        
        // Reset:       Bool (enables other calls being made to this function)
        B_setupArrayIsRunning = NO;
    }];
}
I realized that if I didn't restrict access to this function (using the B_setupArrayIsRunning-var) it could be called more than once before the full table had been saved into the array. This resulted in duplicated posts in the array. Another side-effect of the async request, but using the boolean solves this.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.