Retrieve PFObject from Parse. Not by objectId - ios

I have a table called "UserSnapshot" on Parse and of course you get the objectID's as you populate the table.
However, when I query the table for an object from my app I wont have the object ID's but I will have their "UserCode". I have been playing with something like this.
PFQuery *userProfile = [PFQuery queryWithClassName:#"UserSnapshot"];
[userProfile whereKey:#"Code" equalTo:_Code];
[userProfile getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (!object) {
// Did not find PFObject
// not executed
} else {
// Found PFObject
// also not executed....huh?
}
}];
But nothing happens. Neither the if or the else is entered. Am I missing something?
Thanks

Does anything print out in the log/console? It's possible that you didn't set your keys properly when initializing Parse in your App Delegate.

PFQuery *userProfile = [PFQuery queryWithClassName:#"UserSnapshot"];
[userProfile whereKey:#"Code" equalTo:_Code];
PFObject *object = [userProfile getFirstObject];
Works!

Related

Why is my NSMutable not being populated correctly when inserting objects from another NSArray?

I have a PFQuery that gets the current participants of a particular event:
PFQuery *getcurrentparticipants = [PFQuery queryWithClassName:#"Event"];
[getcurrentparticipants selectKeys:#[#"Participants"]];
[getcurrentparticipants whereKey:#"objectId" equalTo:ObjectID];
[getcurrentparticipants findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSMutableArray *newParticipantsArray = [[NSMutableArray alloc]init];
if([objects[0] valueForKey:#"Participants"] == nil){ // If object retrieved in objects is null. If there are 0 participants
[newParticipantsArray addObject:PFUser.currentUser.username];
PFQuery *query = [PFQuery queryWithClassName:#"Event"];
[query getObjectInBackgroundWithId:self.ObjectID
block:^(PFObject *Event, NSError *error) {
Event[#"Participants"] = newParticipantsArray;
[Event incrementKey:#"Vacants" byAmount:[NSNumber numberWithInt:-1]];
[Event saveInBackground];
}];
}else{ // STEP 5
for(int i=0;i<objects.count;i++) {
[newParticipantsArray addObject:[[objects objectAtIndex:i] valueForKey:#"Participants"]];
}
[newParticipantsArray addObject:PFUser.currentUser.username];
NSLog(#"Part to upload %#", newParticipantsArray);
PFQuery *query = [PFQuery queryWithClassName:#"Event"];
[query getObjectInBackgroundWithId:self.ObjectID
block:^(PFObject *Event, NSError *error) {
Event[#"Participants"] = newParticipantsArray;
[Event incrementKey:#"Vacants" byAmount:[NSNumber numberWithInt:-1]];
[Event saveInBackground];
}];
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
This is how the method works:
Create a PFQuery object
Query the Participants Class for an specific ObjectId
If no error, then we create a NSMutable array
If no participants are in Parse then we insert the current user as participant.
Else, insert all participants in the mutable array and add currentuser at the end of the array.
Then upload it again to Parse
My problem is in step 5:
When I perform the tasks in the else, the column in Parse looks like this :
[["Participant 1"],"Participant 2"]
But I would like to have it like this:
["Participant 1","Participant 2"]
What I have tried:
I tried things like putting the arrays like this. [newParticipantsArray addObject:[[objects objectAtIndex:i] valueForKey:#"Participants"]]; and similar combinations, of course without luck.
It’s hard to say for sure since I can’t see the structure of your data but are you sure the value held in
[[objects objectAtIndex:i] valueForKey: #“Participants”]
Is a single user and not itself an array of users? The plural key “participants” seems to suggest it’s an array of users which would also explain the result you’re getting.
If in fact the value returned for the "Participants" key is an array, you can add the objects in it to your mutable array by doing the following:
NSArray* participants = [[objects objectAtIndex:i] valueForKey:#"Participants"]
[newParticipantsArray addObjectsInArray:participants];
This uses the addObjectsInArray: method of NSMutableArray to add the objects from the old array into the new one.

Having trouble passing PFUser as a PFObject

so in my app, I want to implement user profiles by clicking on a UIButton, I have all the functionality done.
I first added the functionality when the indexPath.section is selected the user information is shown, so then I wanted to do the same thing through a button.
heres my code in -(void)didSelectRow
PFObject *object = [self.objects objectAtIndex:selectedRow];
PFUser *user = [object objectForKey:#"userTookPhoto"];
self.userInfo = user;
self.userInfo is a property PFUser in the .h file
Then in my PrepareSegue I have this :
else if ([segue.identifier isEqualToString:#"homeToProfile2"])
{
transfer.userInformationObject = self.userInfo;
}
I run the app, and i tap on the button to push segue and the app crashes saying that self.userInfo is NULL.
When I NSlog it in didSelectRow, it has the information correct with all the user details,
when I NSlog it in the prepareSegue it crashes as it says it is NULL.
If you want to access PFObjects objects within a PFObject, you need to include within your PFQuery the includeKey: method and pass in the field that the PFObject is...
So if your accessing a PFUser object within a PFObject whose classname is 'Message', you create the query like so...
PFQuery *query = [PFQuery queryWithClassname:#"Message"];
[query whereKey:#"toUser" equalTo:[PFUser currentUser]];
[query includeKey:#"toUser"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error){
for (PFObject *obj in objects) {
NSLog(#"%#", [obj objectForKey:#"toUser"]);
}
}];
The log statement will return the PFUser object.
Heres a link to an explanation of your problem on Parse Blog

Parse Custom cell show image according to boolean

I want to set ImageView hidden or not according to the boolean value true x false, which is located in Parse database. Could you give me some ideas how to do that? Got problems because of having property ImageView in my CustomCell.h
EDIT:
PFObject *yes = [PFObject objectWithClassName:#"MyClass"];
cell.discounts.hidden = [yes[#"yesnocolumn"] boolValue];
I just don`t understand to usage of PFObject, myclass returning (null) value.
EDIT2:
PFQuery *query = [PFQuery queryWithClassName:#"Classname"];
[query whereKey:#"yesnocolumn" equalTo:#1];
[query findObjectsInBackgroundWithBlock:^(NSArray *results, NSError *error) {
if (!error) {
cell.discounts.hidden = YES;
}else{
cell.discounts.hidden = NO;
}}];
The boolean from the service will look like either #0 or #1, so you can't just test for truthiness, because:
if (#0) {
// this condition is true. that's surprising!
}
So the safe way to test is to say:
cell.imageView.hidden = [myParseObject[#"hidden"] boolValue];
EDIT - Now I understand the misunderstanding. Here's how parse works:
1) Create an object locally:
PFObject *yes = [PFObject objectWithClassName:#"MyClass"];
This object won't have any values initialized. So any bools it contains will be 0, or NO.
2) Set some value locally:
yes[#"yesnocolumn"] = #1; // makes it true
// or = [NSNumber numberWithBool:YES];
3) Save it. (you can also use the data browser to initialize objects manually).
[yes saveInBackground];
4) Get an object. I think this is the part that's giving you trouble... just creating a local object doesn't really do much. The idea of parse is that objects are stored in the cloud. To get them, you need a PFQuery.
PFQuery *query = [PFQuery queryWithClassName:#"MyClass"];
[query findObjectsInBackgroundWithBlock:^(NSArray *results, NSError *error) {
// this will return all (up to 100 by default, MyClass objects that are
// saved in the cloud
if (!error && results.count) {
NSLog(#"the first object is %#", results[0]);
NSLog(#"the bool is %d", [results[0][#"yesnocolumn"] boolValue];
}
}];
Does this make sense? You can't expect the object to have any values initialized until you either set them locally, or retrieve already initialized remote copies. Also note, if you run the query on the next source line after saveInBackground, you won't get the saved result, since the save won't have finished. Start out saving in one run of your app, then reviewing in the data browser, then do a query.
It's worth doing a thorough review of their docs here.

Query on Parse relational data is not coming back ordered using orderedByAscending

I'm querying relation data on parse and I would like the objects to come back ordered by the date they were created. I've had this method work before but haven't been able to get an ordered query using relational data. The query return is in a random order. Thanks in advance! Here's my code:
PFQuery *postQuery = [PFQuery queryWithClassName:#"Post"];
[roomQuery whereKey:#"name" equalTo:self.postName];
NSError *error;
//done on main thread to have data for next query
NSArray *results = [postQuery findObjects:&error];
PFObject *post;
if ([results count]) {
post = [results objectAtIndex:0];
NSLog(#"results were found");
} else {
NSLog(#"results were not found");
}
PFRelation *commentsRelation = [#"Comments"];
[commentsRelation.query orderByAscending:#"createdAt"];
[commentsRelation.query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error Fetching Comments: %#", error);
} else {
NSArray *comments = objects;
}
I'm a little confused by your code,
you create a "postQuery", and call it, but never use any of its data.
There's also a roomQuery that never seems to have been allocated, or used.
You're querying a specific post by its name. Are you controlling its name? If not, you should use id's
what is PFRelation commentsRelation = [#"Comments"];
Probably because it's just a snippet, this stuff is dealt with elsewhere; however, for my answer, I'm assuming that your "comments" field is an array of "Comment" class objects.
Option 1:
PFQuery * postQuery = [PFQuery queryWithClassName:#"Post"];
[postQuery whereKey:#"name" equalTo:self.postName];
// again, possibly an id field would be more reliable
// [postQuery whereKey:#"objectId" equalTo:self.postId];
[postQuery includeKey:#"Comments"];
PFObject * post = [postQuery getFirstObject];// no need to download all if you just want object at [0]
// this will contain your post and all of it's comments with only one api call
// unfortunately, it's not sorted, so you would have to run a sort.
NSArray * comments = [post[#"Comments"] sortedArrayUsingComparator: ^(id obj1, id obj2) {
return [obj1[#"createdAt" compare: obj2[#"createdAt"];
}];
Option 2:
Perhaps a better option is to rework your data structure and instead of associating the comments to the post, you could associate the post to the comments (as in the parse docs)
PFQuery * postQuery = [PFQuery queryWithClassName:#"Post"];
[postQuery whereKey:#"name" equalTo:self.postName];
// again, possibly an id field would be more reliable
// [postQuery whereKey:#"objectId" equalTo:self.postId];
PFQuery * commentQuery = [PFQuery queryWithClassName:#"Comment"];
[commentsQuery whereKey:#"parent" matchesQuery:postQuery]; // when creating a comment, set your post as its parent
[commentsQuery addOrderDescending:#"createdAt"]
[commentQuery findObjectsInBackgroundWithBlock:^(NSArray *comments, NSError *error) {
// comments now contains the comments for myPost
}];
Both of the above solutions avoid making extra unnecessary api calls (parse charges based on calls after all!).

PFQuery Matches Query not Working Parse.com

Hello everyone I'm trying to merge two queries with MatchesQuery but the data on the TableView will not be displayed and gives me this error
Error: bad type for $ inquery
Does anyone know what is the error in this query? Thanks to all
- (void) retrieveFromParse {
PFQuery *Amici = [PFQuery queryWithClassName:#"Amicizie"];
[Amici whereKey:#"RICHIESTA_IN_ATTESA" equalTo:#"YES"];
PFQuery *retrievePets = [PFQuery queryWithClassName:FF_USER_CLASS];
[retrievePets whereKey:FF_USER_NOMECOGNOME matchesQuery:Amici];
[retrievePets orderByAscending:FF_USER_NOMECOGNOME];
[retrievePets findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSLog(#"%#", objects);
allObjects = [[NSMutableArray alloc] init];
for (PFObject *object in objects) {
[allObjects addObject:object];
}
}
[self.FFTableViewFindUser reloadData];
}];
}
Given that you are querying on a boolean value, you should look at this question.
Basically you need to do this:
[Amici whereKey:#"RICHIESTA_IN_ATTESA" equalTo:[NSNumber numberWithBool:YES]];
That may be all you need. If not it will get you another error message to help you get to the root of the issue.
You can add a "amiciString" column which holds the string value. Then you can do this:
[retrievePets whereKey:#"FF_USER_NOMECOGNOME" matchesKey:#"amiciString" inQuery:Amici];
Try! I hope it works!

Resources