0

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.

2 Answers 2

1

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;

Sign up to request clarification or add additional context in comments.

Comments

1

(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!

5 Comments

I realize that if I NSLog right after assigning the messages array to = objects that it will show up in my debug. That has never been a problem. The reason I NSLogged it out of the callback is to illustrate that the messages array is NOT being set OUTSIDE the callback - that is the problem. Which I need to be able to do in order to create an array of all of the callbacks so that I can sort them the way you described (by the way, outstanding thank you) so that I can populate my tableView with the array.
I guess you're missing something. You have to assign your array in the callback, and then force your table view to reload using reloadData selector, still in the callback, right after having assigned your array. Your assignment is applied outside of the callback, but only once the callback is called.
I tried orQueryWithSubqueries. It errored out this... *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'All sub queries of an or query should be on the same class'
Seems like it's impossible to use this method in your case, keep the version you posted before instead. Please vote up if my answers helped you!
Read the second part of my original answer, and keep a reference using a property on the final array. You may consider getting the basics of objective-c and cocoa development.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.