Reputation: 671
I am all new to Parse and iOS development. Basically I am trying to implement a method for retrieving parse objects in the one class, which other classes will call with an entityName to return objects. So another class will call the method retrieveRecords
with the entityName
as the parameter.
However the array always returns nil as the block method doesn't get executed until after the array is returned. Before (when my fetching objects worked!) I had just a method for retrieving objects in the same class that I needed the data so I just declared a __block
array to return the data.
I know this is a common problem as I googled it extensively but I can't seem to find the right solution for returning an array of objects to another class and have ended up with more tangled code which doesn't work.
- (void)doQuery:(NSString *)entityName
{
//Create query for all Post object by the current user
PFQuery *workoutQuery = [PFQuery queryWithClassName:entityName];
[workoutQuery whereKey:@"owner" equalTo:[PFUser currentUser]];
// Run the query
[workoutQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
//Save results and update the table
NSLog(@"Adding objects to the array");
NSLog(@"Size %lu" , (unsigned long)objects.count);
//fill the array once the block is BEING EXECUTED
[self successfulRetrievedArray:objects];
}
}];
}
-(NSArray *)successfulRetrievedArray:(NSArray *)objects
{
self.objectsArray =[[NSMutableArray alloc]initWithArray:objects];
return self.objectsArray;
}
-(NSArray *)retrieveRecords:(NSString *)entityName
{
//DO QUERY
[self doQuery:entityName];
//RETRIEVE RECORDS
return self.objectsArray;
}
Upvotes: 2
Views: 466
Reputation: 4012
- (void)doQuery:(NSString *)entityName withCompletionBlock:(void (^)(NSArray *objects, NSError *error))completionBlock {
//Create query for all Post object by the current user
PFQuery *workoutQuery = [PFQuery queryWithClassName:entityName];
[workoutQuery whereKey:@"owner" equalTo:[PFUser currentUser]];
// Run the query
[workoutQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
//Save results and update the table
NSLog(@"Adding objects to the array");
NSLog(@"Size %lu" , (unsigned long)objects.count);
//fill the array once the block is BEING EXECUTED
[self successfulRetrievedArray:objects];
if (completionBlock) {
completionBlock(objects, nil);
}
} else {
if (completionBlock) {
completionBlock(nil, error);
}
}
}];
}
Replace your code with that one above. And just put login with array into completion block
Upvotes: 2
Reputation: 119031
The best approach is to add a parameter to doQuery:
so that the caller can supply a completion block. That block would take the received array as a parameter and is called when the array has been received.
By doing this you embrace that fact that the data collection is asynchronous and cater for that in the method.
Storing the result in self.objectsArray
isn't great because there is no notification to the caller that the data is ready, and only one call can be in progress at a time (because there is only one place to store the result).
Upvotes: 1