简体   繁体   中英

How can I populate a UITableView with data from a parse.com query after it is done running in the background?

I have a UITableViewController that is in charge of displaying a table full of employees. This data is being stored on a database on parse.com.

This is my UITableViewController , in which I just initiate the store:

-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
    self = [super initWithNibName:nil bundle:nil];
    if(self){
        store = [[EmployeeStore alloc] init]; 
    }
    return self;
}

This is the EmployeeStore init method, in which i query for the employees:

-(id) init{
    self = [super init];
    if(self){
        employees = [[NSMutableArray alloc] init];
        [self fetchEmployeesFromDatabase];
    }
    return self;
}

fetchEmployeesFromDatabase , where I query for the employees.

-(void) fetchEmployeesFromDatabase{
    PFQuery *query = [PFQuery queryWithClassName:@"Employee"];
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error) {
            // The find succeeded.
            NSLog(@"Successfully retrieved %d scores.", objects.count);
            // Do something with the found objects
            for (PFObject *object in objects) {
                NSLog(@"%@", object.objectId);
                [employees addObject:object]; 
            }
        } else {
            // Log details of the failure
            NSLog(@"Error: %@ %@", error, [error userInfo]);
        }
    }];
}

I am successfully receiving them, however the problem is the query takes place in the background, and does not finish until after the table view is done loading, so the table view does not populate. I need to have the table reload its data after the query is complete but how do I go about doing this?

UITableViewController

-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
    self = [super initWithNibName:nil bundle:nil];
    if(self){
        store = [[EmployeeStore alloc] init];
        store.tableView = self.tableView; 
    }
    return self;
}

EmployeeStore.h

@property (nonatomic, strong) UITableView *tableView;

EmployeeStore.m

-(id) init{
    self = [super init];
    if(self){
        employees = [[NSMutableArray alloc] init];
        [self fetchEmployeesFromDatabase];
    }
    return self;
}

and fetchEmployeesFromDatabase

-(void) fetchEmployeesFromDatabase{
    PFQuery *query = [PFQuery queryWithClassName:@"Employee"];
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error) {
            // The find succeeded.
            NSLog(@"Successfully retrieved %d scores.", objects.count);
            // Do something with the found objects
            for (PFObject *object in objects) {
                NSLog(@"%@", object.objectId);
                [employees addObject:object]; 
            }

             dispatch_async(dispatch_get_main_queue(), ^ {
                [self.tableView reloadData];
              });

        } else {
            // Log details of the failure
            NSLog(@"Error: %@ %@", error, [error userInfo]);
        }
    }];
}

When the load completes tell the table view to reload.

if (!error) {
    // The find succeeded.
    NSLog(@"Successfully retrieved %d scores.", objects.count);
    // Do something with the found objects
    for (PFObject *object in objects) {
        NSLog(@"%@", object.objectId);
        [employees addObject:object]; 
    }

    dispatch_async(dispatch_get_main_queue(), ^ {
        [tableView reloadData];
    });
} else {

You need to ensure that your employees store is thread safe or is not accessed by the background and main threads concurrently.

-(void) fetchEmployeesFromDatabase{
PFQuery *query = [PFQuery queryWithClassName:@"Employee"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
    if (!error) {
        // The find succeeded.
        NSLog(@"Successfully retrieved %d scores.", objects.count);
        // Do something with the found objects
        for (PFObject *object in objects) {
            NSLog(@"%@", object.objectId);
            [employees addObject:object]; 
        }
    } else {
        // Log details of the failure
        NSLog(@"Error: %@ %@", error, [error userInfo]);
    }
    [self performSelectorOnMainThread:@selector(reloadTableView) withObject:nil waitUntilDone:NO];
}];
}

-(void)reloadTableView{
    [self.aTableview reloadData];
}

Now you load your tableview on mainthread. Try this.

Here the data gets populated into the table even before the table view is completed. All you need to do here is place the statement [self fetchEmployeesFromDatabase]; inside viewDidLoad() method or whichever method which invokes your table creation .

I had this problem, except for collection view. After a lot of pain, this did the trick to reload the data via the main thread.

dispatch_async(dispatch_get_main_queue(), ^ {
            [self.collectionView reloadData];
            [self.collectionView reloadItemsAtIndexPaths:[self.collectionView   indexPathsForVisibleItems]];
        });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM