Tom Testicool
Tom Testicool

Reputation: 563

iOS Parse SDK: Multiple query results put into an Array

Scenario = I have an app where users can send each other Messages, Comments, and Pokes that are queried to populate the current user's notificationsTableView. There are 3 queries that must take place, one for Messages, two for Comments, and three for Pokes. The code I'm using is below...

PFQuery *messageQuery = [PFQuery queryWithClassName:@"Message"];
[messageQuery whereKey:@"receiverID" equalTo:[PFUser currentUser][@"userID"]];
[messageQuery orderByDescending:@"createdAt"];
[messageQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {

    messages = objects;    

}];

PFQuery *pokeQuery = [PFQuery queryWithClassName:@"Poke"];
[pokeQuery whereKey:@"receiverID" equalTo:[PFUser currentUser][@"userID"]];
[pokeQuery orderByDescending:@"createdAt"];
[pokeQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {

    pokes = objects;    

}];

PFQuery *commentsQuery = [PFQuery queryWithClassName:@"Comment"];
[commentsQuery whereKey:@"receiverID" equalTo:[PFUser currentUser][@"userID"]];
[commentsQuery orderByDescending:@"createdAt"];
[commentsQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {

    comments = objects;    

}];

What is desired = To consolidate the following arrays: "messages", "pokes", and "comments" into a single array (notificationsArray) that I can sort by "createdAt" and populate my notificationsTableView with notificationsArray objectAtIndexPath:indexPath.row.

Problems I have encountered = (there are two)

(1) When I NSLog the results of any of these queries like so...

PFQuery *messageQuery = [PFQuery queryWithClassName:@"Message"];
[messageQuery whereKey:@"receiverID" equalTo:[PFUser currentUser][@"userID"]];
[messageQuery orderByDescending:@"createdAt"];
[messageQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {

    messages = objects;    

}];

NSLog(@"messages = %@", messages);

It logs "messages = (null)". I can not for the life of me figure out why it is not being set. I know there are messages because when I NSLog the "objects" Array that comes from the query it gives me what I want. It's like the contents of the query will not leave the scope of the query itself. All of the queries above do this. If I can not get the contents of the query out of that block then I can not create an array of all of the arrays to populate the notificationsTableView with, so I'm screwed. Please help.

(2) Even if I do get the results from the queries into individual arrays, I am not sure how to create an array of arrays and order them by a key. Can anyone help me with this? Please.

Upvotes: 0

Views: 1081

Answers (2)

sweepy_
sweepy_

Reputation: 1331

(1) You are logging messages outside of the callback function, and the log comes before the callback function returned. Try to log messages into your callback, just after assigning it.

[messageQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
    messages = objects;    
    NSLog(@"messages = %@", messages)
}];

(2) Before sorting, create a NSMutableArray and use the addObjectsFromArray: method with each retrieved array.

To sort notifications, you should use a NSSortDescriptor, which is a mechanism that describes how to sort an array according to the format of contained objects. Here's an example that could match your needs:

NSSortDescriptor *createdAtDescriptor = [[NSSortDescriptor alloc] initWithKey:@"createdAt" ascending:YES];
notificationsArray = [messages sortedArrayUsingDescriptors:@[createdAtDescriptor]];

Hope this help!

EDIT: you can embed your temporary NSMutableArray into an autorelease pool to avoid useless memory leaks, so that the dedicated memory is freed just after you proceed to display.

EDIT: you can use orQueryWithSubqueries Parse method to merge several requests into a single one. It's not annoying in your case cause you're sorting PFObject according to their createdAt key, which is common to every PFObject. In any case, you will have to check PFObject types to display them according to their type. Please see full documentation here. Does not work for queries returning several kind of objects!

Upvotes: 1

Daddy
Daddy

Reputation: 9035

You are probably looking for the +orQueryWithSubqueries:(NSArray *)queries method, but I don't understand what the return value description is:

a PFQuery that is the or of the passed in PFQueries

I'm thinking this means || (or) ?

You would do it like this:

NSArray *queryArray = [NSArray arrayWithObjects:messageQuery,pokeQuery,commentsQuery,nil];
PFQuery *allQueries = [PFQuery orQueryWithSubqueries:queryArray];
[allQueries findObjects... {

As for the second error, you are right, value is not retained because when the block loses scope all of the local variables inside get destroyed in the autoreleasepool. You need to retain this by using a strong property. self.messages = objects;

Upvotes: 1

Related Questions