PFQuery orSubQuery for PFQueryTableViewController not working - ios

I had a table view working off of a compound query, and I updated Parse and now it seems to not work anymore. I'm not sure if it's the Parse update, but here's the situation:
The query is as follows (in the queryForTable method (which is called) of the PFQueryTableViewController):
self.parseClassName = #"Event";
PFQuery *attendeeQuery = [PFQuery queryWithClassName:self.parseClassName];
PFQuery *organizerQuery = [PFQuery queryWithClassName:self.parseClassName];
[attendeeQuery whereKey:#"attendees" containsAllObjectsInArray:[NSArray arrayWithObjects:[PFUser currentUser], nil]];
[organizerQuery whereKey:#"organizer" equalTo:[PFUser currentUser]];
PFQuery *query = [PFQuery orQueryWithSubqueries:#[organizerQuery, attendeeQuery]];
[query includeKey:#"organizer"];
[query whereKey:#"isVisible" equalTo:[NSNumber numberWithBool:YES]];
[query orderByAscending:#"time"];
return query;
When I run this query, objectsDidLoad never gets called and my table view hangs in the loading state. Help please!

The solution has to do with the one line I didn't include above.
I had this:
if ([self.objects count] == 0) {
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
}
and it turns out in the most current Parse SDK and iOS SDK, cachePolicy is broken, so one must use kPFCachePolicyIgnoreCache to get results when using a where ContainedIn clause.
Source:
https://developers.facebook.com/bugs/717037238403238/

Related

How to access fields of a pointer's value on parse.com with iOS?

I am designing a database. According to documentation, when number of relationships are greater than 100 and there is extra fields, I must design a Join Table. I designed this Join Table by having two pointer value.
This pointer value is pointing to _User. Later I need only rows for currUser.
This pointer value is the objectId of another table which is an entity. My question is, how can I write a query to return objects for this table in queryfortable.
Let's say:
Table _User
Table Entity
Table Join ---> objectId Pointer1(_User) Pointer2(Event)
This look like this:
This is what I have tried so far:
First I tried in viewDidLoad to get array of invitedUser from cloud and later in queryForTable:
PFQuery *query = [PFQuery queryWithClassName:#"Event"];
[query whereKey:#"objectId" containedIn:_inviteList];
but I need to access _inviteList.objectId which is not possible!
I tried to use innerQuerry or relation query. but as I just started learning parse I am not able to implement this.
PFUser *friendPointer = [PFUser currentUser];
PFQuery *query2 = [PFQuery queryWithClassName:#"Event"];
[query2 whereKey:friendPointer containedIn:_inviteList];
return query2;
This also did not work for me.
PFQuery *innerQuery = [PFQuery queryWithClassName:#"Invite"];
[innerQuery whereKey:#"invitedUser" equalTo:[PFUser currentUser]];
query = [PFQuery queryWithClassName:#"Event"];
[query whereKey:#"user" matchesQuery:innerQuery];
return query;
I appreciate if anyone can help me to write this query or re-design my table in order to have access to this query.
Pleaser try this code and give me review
PFUser *user = [PFUser currentUser];
PFQuery *query = [PFQuery queryWithClassName:#"Invite"];
[query whereKey:#"invitedUser" equalTo:user];
[query includeKey:#"invitedUser"];
[query includeKey:#"eventId"];
[query orderByDescending:#"updatedAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if (error == nil)
{
for (PFObject *underobject in [objects reverseObjectEnumerator])
{
PFUser *user1 = underobject[#"invitedUser"];
NSLog(#"invitedUser is :%#",user1);
}
}
}];

IOS Parse Queries

I am trying to parse some objects from my data base. I'm using parse.com as web service.
The following code gives me back some object based on 4 queries, 2 of them being compound.
The variable "meetingAge" must be equal to indexAge OR "6"
The variable "meetingSex" must be equal to "sex" OR "2"
The variable "isAvaiable" must be equal to YES
The variable "author" must be different from user.username
Basically i am trying to implement a query with 2 OR conditions and 2 AND conditions.
The following code gives me a wrong result, no exceptions or stuff like that, just a wrong kind of object. I'm sure it's a syntax issue but i can't figure out how to properly write this..If i just use 1 compound query and then add the 2 AND queries to that i get a right result, but then i miss 1 filter..
PFQuery *queryAge1 = [PFQuery queryWithClassName:#"MeetingObject"];
[queryAge1 whereKey:#"meetingAge" equalTo:indexAge ];
PFQuery *queryAge2 = [PFQuery queryWithClassName:#"MeetingObject"];
[queryAge2 whereKey:#"meetingAge" equalTo:#"6"];
PFQuery *queryCompound = [PFQuery orQueryWithSubqueries:#[queryAge1,queryAge2]];
PFQuery *querySex1 = [PFQuery queryWithClassName:#"MeetingObject"];
[querySex1 whereKey:#"meetingSex" equalTo:user[#"sex"]];
PFQuery *querySex2 = [PFQuery queryWithClassName:#"MeetingObject"];
[querySex2 whereKey:#"meetingSex" equalTo:#"2"];
queryCompound = [PFQuery orQueryWithSubqueries:#[querySex1,querySex2]];
[queryCompound whereKey:#"isAvaiable" equalTo:[NSNumber numberWithBool:YES]];
[queryCompound whereKey:#"author" notEqualTo:user.username];
[queryCompound findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
}
In your line... queryCompound = [PFQuery orQueryWithSubqueries:#[querySex1,querySex2]]; you are creating a brand new query ignoring all the age stuff.
EDIT
You are overcomplicating this.
You can do this this way...
PFQuery *query = [PFQuery queryWithClassName:#"MeetingObject"];
[query whereKey:#"meetingAge" containedIn:#[#"6", indexAge]];
[query whereKey:#"meetingSex" containedIn:#[#"2", user[#"sex"]]];
[query whereKey:#"isAvaiable" equalTo:[NSNumber numberWithBool:YES]];
[query whereKey:#"author" notEqualTo:user.username];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
}
This will catch all the options you are looking for.
Also, just as a quick note. Choose your variable names to make them more readable. If they all begin with the word query it's hard to distinguish them. Also make them descriptive. queryAge1 and queryAge2 makes it harder to understand what they are doing.

Parse Query Constraint Contained In Not Returning Objects

I am trying to run this query however it is returning no objects. Any help?
for (int arrayIndex=0; arrayIndex<[self.cards count]; arrayIndex++)
{
NSString *senderId = [[deck objectAtIndex:arrayIndex]objectForKey:#"SenderId"];
[list_of_sender_ids addObject:senderId];
}
PFQuery *query = [PFQuery queryWithClassName:#"User"];
[query whereKey:#"facebook_id" containedIn:list_of_sender_ids];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
A couple of things that could be going wrong right off the bat:
First of all, to query the user class, you shouldn't use
PFQuery *query = [PFQuery queryWithClassName:#"User"];
But instead,
PFQuery *query = [PFUser query];
Assuming your User class still returns PFUser objects.
Another thing to make sure is right is the #"Facebook_id" key, and confirm in Parse that this is a top level key that you can see on your Parse User objects.
Lastly, make sure #"SenderId" is also the right key on the objects in deck, since you seem not to be querying based on the same key that could cause the issue.

parse.com: How to compare pointer-keys with objects?

I am using the backend service parse.com for a iOS app and I have a problem with querying it properly. I need help with the method whereKey:matchesKey:inQuery;
I have this code:
//NOT WORKING
PFQuery *query1 = [PFQuery queryWithClassName:#"Object"];
PFQuery *query2 = [PFQuery queryWithClassName:#"ObjectsRelations"];
[query2 whereKey:#"user" equalTo:[PFUser currentUser]];
[query1 whereKey:#"objectId" matchesKey:#"objectPointer" inQuery:query2];
[query1 findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// No objects
}];
It is not working the way I want. I have tried several ways for it to compare the key "objectPointer" in class "ObjectsRelations" (which is a pointer to an instance of class Object) to the actual Object in query 1. I do not get any objects back, because the comparison does not work as I want, since the key objectId is just a string and the key objectPointer is a pointer to a Object.
When I run this code, I get the intended result, but this requires me to do two api-requests to get the actual objectId as a string!
//WORKING
PFQuery *query = [PFQuery queryWithClassName:#"Object"];
PFQuery *query2 = [PFQuery queryWithClassName:#"ObjectRelations"];
[query2 whereKey:#"user" equalTo:[PFUser currentUser]];
[query2 findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
PFObject *firstObject = [((PFObject*)[objects firstObject]) objectForKey:#"objectPointer"];
[query whereKey:#"objectId" equalTo:firstObject.objectId];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
//Getting the objects correctly from the class Object!
}];
}];
How to do this with a single api-request? How to compare a instance of a Class to a pointer of a class with a query?
Something like this is what i want to do: (Pseudo Code)
[query1 where:SELF matches:#"objectPointer" inQuery:query2];
Any suggestions?
I just searched this exact same problem and there are a number of questions on the Parse forum regarding it:
Trouble with nested query using object_id
Assistance with relational query
Compare string to pointer in query with does not match key in query
The first one explains a hack to include an extra field (in this case) in your ObjectRelations class. This key/field would be a string that would be the objectId of the pointer. It would be in addition to the key/field that holds the pointer.
If you look through the questions you can see that as of now there doesn't seem to be an answer directly from Parse regarding this.
Instead of adding an additional column with type String to contain the objectID it points to, I would suggest to add a column on each object with type Pointer to point to the object itself. This would dramatically reduce the amount of the columns you have to add. The only downside is this must be done on Cloud Code.
At this question's scenario, you'll have two queries like:
//Inner query
//Library containing pointer<Deck> & pointer<User>
PFQuery * subscriptions = [PFQuery queryWithClassName:#"subscription"];
[subscriptions whereKey:#"User" equalTo:[PFUser currentUser]];
//Outer query
//Pull down a list of deckStore objects not included in the subscriptions for current user
PFQuery * decks = [PFQuery queryWithClassName:#"deckStore"];
Then instead of:
[decks whereKey:#"objectId" doesNotMatchKey:#"deckString" inQuery:subscriptions];
You can do this:
[decks whereKey:#"this" doesNotMatchKey:#"deck" inQuery:subscriptions];
Here's a sample of what the Cloud Code should be added:
Parse.Cloud.afterSave("Deck", function(request) {
var deck = request.object;
// To make sure this is the first time of "afterSave" of this object.
if (deck.createdAt.getTime() == deck.updatedAt.getTime()) {
// "this" is the column which contains the pointer of the object itself.
if (deck.get("this") == null) {
deck.set("this", deck);
deck.save();
}
}
}
I have the same problem. This is my solution:
PFQuery *query1 = [PFQuery queryWithClassName:#"tableClass"];
[query1 whereKey:#"objectId" equalTo:[(PFObject *)[object objectForKey:#"pointerField"] objectId]];
PFObject *obj1 = [query1 getObjectWithId:[(PFObject *)[object objectForKey:#"pointerField"] objectId]];
NSString *pointerName = [obj1 objectForKey:#"name"];

Parse.com -- Add on values from a second class/object

So I'm using Parse.com and their AnyPic app as a starting point. It's an Instagram clone. However, unlike Instagram, the comments for pictures aren't included on home page. You have to tap the picture and it brings up a DetailsVC with the commments. This is the first thing I'm trying to change.
I'm new to Parse (and backends in general) and am having trouble trying to modify the query to return the comments. If you've used AnyPic, you know that the comments aren't saved in the Photo class but in a separate Activity class:
Activity.type would equal comment and Activity.content would be the comment text.
SO, the VCs in AnyPic subclass Parse's PFQueryTableViewController, overriding the queryForTable method to fetch data. Here's the queryForTable for their AccountVC, which returns ONLY the photos:
- (PFQuery *)queryForTable {
if (!self.user) {
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
[query setLimit:0];
return query;
}
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
query.cachePolicy = kPFCachePolicyNetworkOnly;
if (self.objects.count == 0) {
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
}
[query whereKey:kPAPPhotoUserKey equalTo:self.user];
[query orderByDescending:#"createdAt"];
[query includeKey:kPAPPhotoUserKey];
return query;
}
And the queryForTable for the DetailsVC, which will return comments for the photo object passed to it in self.photo:
- (PFQuery *)queryForTable {
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
[query whereKey:kPAPActivityPhotoKey equalTo:self.photo];
[query includeKey:kPAPActivityFromUserKey];
[query whereKey:kPAPActivityTypeKey equalTo:kPAPActivityTypeComment];
[query orderByAscending:#"createdAt"];
[query setCachePolicy:kPFCachePolicyNetworkOnly];
// If no objects are loaded in memory, we look to the cache first to fill the table
// and then subsequently do a query against the network.
//
// If there is no network connection, we will hit the cache first.
if (self.objects.count == 0 || ![[UIApplication sharedApplication].delegate performSelector:#selector(isParseReachable)]) {
[query setCachePolicy:kPFCachePolicyCacheThenNetwork];
}
return query;
}
I just can't wrap my head around how to combine the two queries into one and have it return photo objects with comment values attached.
I've thought to just run a separate query for the comments in tableView:numberOfRowsInSection: once queryForTable returns a set of photos, but I'm thinking it's better if I let Parse's queryForTable handle it in case there's some caching going on that might be useful.

Resources