IncrementKey of Parse api not incrementing - ios

I have a problem with incrementKey. I'd like to increment two keys of my user class, and they're not incrementing. Here's my code, if you want more details feel free to ask.
- (void) updateUserNbrQuestionsAnswered: (NSString*)FacebookID;
{
NSLog(#"%#", FacebookID);
PFQuery *queryUser = [PFQuery queryWithClassName:#"User"];
[queryUser whereKey:#"FacebookID" equalTo:FacebookID];
PFObject *user = [queryUser getFirstObject];
[user incrementKey:#"NbrQuestionsAnswered" byAmount:[NSNumber numberWithInt:1]];
[user incrementKey:#"Points" byAmount:[NSNumber numberWithInt:5]];
[user save];
};
I call this function every time the user hits a button, which reload the view after incrementing on parse and updating a label. Thanks in advance for your help !

Use this:
PFQuery *queryUser = [PFUser query]
Change the save method with
PFObject* user;
...
..
.
NSError* anyErr = NULL;
[user save:&anyErr];
Ensure you have the write permission to alter the values of the User table (see ACL)

Related

Retrieve data from one column in one row

I have a class (table) in Parse.com core data called users with username, name, surname, email and password.
I want to retrieve, for example, only the name column but I can't make this work. Here is the code:
PFQuery *query = [PFQuery queryWithClassName:#"user"]; //1
[query whereKey:#"email" equalTo:_labelEmail.text];//2
[query findObjectsInBackgroundWithBlock:^(NSArray *userData, NSError *error) {//4
if (!error) {
NSLog(#"%#", usuario);
} else {
NSString *errorString = [[error userInfo] objectForKey:#"error"];
NSLog(#"Error: %#", errorString);
}
}];
I know userData is an array not a dictionary but then how can I retrieve only the information I want? I did try to pull the userData as a dictionary instead of an array but the query does not let me do that.
What I want to do is something like:
NSLog(#"%#", userData["name"])
First I would check if your returned array is empty. If it is then no matter what you do you are not going to get the information you need out of the query.
If you are getting an error you should probably think about your query class. You are trying to query on the class "user" whereas I'm guessing you would like to query the built in _User class. To do that you would use a different kind of query:
PFQuery *query = [PFUser query];
Try this query type that Parse gives for this exact purpose and see if your returned data has any valid data. If it does you can either use:
PFUser *user = [userData objectAtIndex:0];
if you know that there should be only one user object returned to you, or you can use:
for(PFUser *user in userData)
{
//Do something with the user object that got returned to you
}

How to run a loop of parse queries?

I am making an app that registers users and allows them to add friends etc. So I have a LoginViewController where I retrieve the array of user's friends' objectIds when the login is successful. This function is called.
- (void) getFriendList
{
NSString * objectID = [PFUser currentUser].objectId;
NSLog(#"%#", objectID);
PFQuery *query = [PFUser query];
[query getObjectInBackgroundWithId:objectID block:^(PFObject *username, NSError *error) {
sharedClass.sharedInstance->retrievedFriends = username[#"friendsIds"];
friendListLoaded = YES;
[self getFriendsUsernames];
}];
Here i get an array object that contains object ids of all the friends this user has. As you can see when getFriendList is completed, it calls another function called GetFriendsUsernames. This function is supposed to retrieve profile pictures and usernames of those friends so I can populate the Friend List view later.
-(void) getFriendsUsernames
{
NSMutableArray * objectIDs = [[NSMutableArray alloc] initWithArray: sharedClass.sharedInstance->retrievedFriends];
PFQuery *query = [PFUser query];
int friendsCount = [objectIDs count];
for(int i = 0; i<=friendsCount;i++)
{
[query getObjectInBackgroundWithId:objectIDs[i] block:^(PFObject *username, NSError *error) {
[sharedClass.sharedInstance->friendsUsernames addObject:username[#"username"]];
[sharedClass.sharedInstance->friendsProfilePictures addObject:username[#"ProfilePicture"]];
}];
NSLog(#"%#", sharedClass.sharedInstance->friendsUsernames );
}
}
But this seems to be unsuccessful because nothing is logged on the console where it should log username of retrieved friend whenever one query gets finished. Am I doing this the right way? My array count is right so loop runs to the number of friends a user has. It also prints the username of first object in objectIds array if i put the logging command in the loop.
Your NSLog runs immediately after your query objects are queued for execution. Therefore, even if the code is running correctly (and I suspect it might not be), you'll never get the correct results you're after logged to the console.
If you have your Parse classes designed in a certain way, you could collapse this into 1 query by using the include method on PFQuery. This assumes that you've created an array of Pointers on your User object, named "friends". If you actually store the objectId (i.e., the string value) of each friend, this code won't work.
I'm not using Swift yet, so here's how I'd write this query in Objective-C:
- (void)getFriendList {
PFUser *currentUser = [PFUser currentUser];
PFQuery *query = [PFUser query];
[query whereKey:#"objectId" equalTo:currentUser.objectId];
[query includeKey:#"friends.username"];
[query includeKey:#"friends.ProfilePicture"];
[query getFirstObjectInBackgroundWithBlock:^(PFObject *user, NSError *error) {
if (error != nil) {
// Process the error
} else }
// You've got your user and the data you wanted
}
}];
}
Found it. Not the prettiest way out there but well it does what i want. gets me arrays of usernames and profile pictures of every objectID contained in array of friends.
NSMutableArray * objectIDs = [[NSMutableArray alloc] initWithArray: sharedClass.sharedInstance->retrievedFriends];
PFQuery *query = [PFUser query];
PFFile * imageFile;
//UIImage *profilePictureData;
int friendsCount = [objectIDs count];
for(int i = 0; i<friendsCount;i++)
{
PFObject * username = [query getObjectWithId:objectIDs[i]];
[sharedClass.sharedInstance->friendsUsernames addObject:username[#"username"]];
[sharedClass.sharedInstance->friendsEmailAdresses addObject:username[#"email"]];
//NSLog(#"%#",username[#"ProfilePicture"]);
imageFile = [username objectForKey:#"ProfilePicture"];
NSData *imageData = [imageFile getData];
UIImage *imageFromData = [UIImage imageWithData:imageData];
[sharedClass.sharedInstance->friendsProfilePictures addObject:imageFromData];
NSLog(#"%#", sharedClass.sharedInstance->friendsUsernames );
}

Query Custom User Class Parse

I'm trying to query three columns that I created in my user class with parse. I successfully saved them to the user class. But I'm having difficulty query these three columns onto a label. I really don't know where to start with the query, I want it to be user specific of course, so user A gets his name, bio, gender, ect. And name is the user's full name, not their username.
This is my code to save the objects:
- (IBAction)save:(id)sender {
PFUser *profile = [PFUser currentUser];
[profile setObject:_name.text forKey:#"Name"];
[profile setObject:_bio.text forKey:#"Bio"];
NSString *var = [[NSUserDefaults standardUserDefaults] objectForKey:#"MyKey"];
[profile setObject:var forKey:#"Gender"];
[profile saveInBackground];
}
For the query I really don't know, this is where I need help. So if you have any suggestions I would appreciate it. Thank you!
Try this one
PFQuery * query = [PFQuery queryWithClassName:#"ClassName"];
[query whereKey:#"Name" equalTo:#"XYZ"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// objects : PFObjects
// you can filter out the data you want and print into lable
}];

Parse Set Object To UILabel

So this is my first time working with parse I have simple application which creates a user and allows them to sign in. I'm currently working on something that will allow them to fill in details about themselves using PFObjects, I don't have a problem with that. My issue is I need to get user specific data print out on an UILabel.
Here's my code creating a PFObject this works fine:
- (IBAction)saveProfile:(id)sender {
PFObject *profile = [PFObject objectWithClassName:#"Profile"];
[profile setObject: self.name.text forKey:#"name"];
[profile setObject:[PFUser currentUser] forKey:#"author"];
[profile saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
NSLog(#"No Error");
}else NSLog(#"Yeah you got an error bro");
}];
}
Here's what I'm having an issue with my PFQuery:
PFQuery *query = [PFQuery queryWithClassName:#"Profile"];
[query whereKey:#"name" equalTo:[PFUser currentUser]];
[query getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (!error) {
NSLog(#"Success");
self.nameLabel.text = [NSString stringWithFormat:#"%#", query];
}
else {
NSLog(#"Fail");
}
}];
}
So basicly I want the user to enter their name have it save, and have that specific user's name print out on a label. This is as far as I got so, if you have any suggestions I'm all ears. Thanks!
Updated:
PFQuery *query = [PFQuery queryWithClassName:#"Profile"];
[query whereKey:#"author" equalTo:[PFUser currentUser]];
[query getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (!error) {
NSLog(#"Success");
self.nameLabel.text = object[#"name"];
}
else {
NSLog(#"Fails");
}
}];
}
Looks like you're setting the PFObject "name" key to self.name.text, but in your PFQuery you're querying the class and asking for values where "name" is equal to [PFUser currentUser]. You're setting the value one way then using a completely different value in an attempt to query the object; so getFirstObjectInBackgroundWithBlock isn't returning an object since there's no Profile object where "name" equals [PFUser currentUser].
I think you're confusing your "name" and "author" properties...
Edit (in response to your comment):
OK, so in saveProfile: you're creating a PFObject where you're setting "name" to the name string and "author" to the user's PFUser object. When you're using whereKey: to perform a query on this class in an effort to retrieve the object using getFirstObjectInBackgroundWithBlock:, the result returned to you will be the full first PFObject where the object associated with the key is the one specified in the whereKey: criteria. So you don't have to specify which key of the PFObject you want to read before performing getFirstObjectInBackgroundWithBlock:. The query returns the whole object -- name, author, etc.
So in order to access the returned PFObject's "name" within the query block, change:
self.nameLabel.text = [NSString stringWithFormat:#"%#", query];
to (dispatch_aync added to force the label change onto the main thread):
dispatch_async(dispatch_get_main_queue(),^{
self.nameLabel.text = object[#"name"];
});
This line
[query whereKey:#"name" equalTo:[PFUser currentUser]];
only works if the "name" column is a pointer or relation to the User class. If it is the username you're after, you need to use
[query whereKey:#"name" equalTo:[PFUser currentUser][#"username"]];
But why are you querying for the object you just saved?
Your last, updated example should work for your need.
You could fire up a query like the one below
PFQuery *query = [PFQuery queryWithClassName:#"Profile"];
NSString *nameStr = [NSString stringWithFormat:#"%#",[[PFUser currentUser]objectForKey:#"name"]];
[query whereKey:#"name" containsString:nameStr];
[query getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error)
{
if (!error)
{
/*object contains all columns and you need only key to obtain value*/
nameLabel = [NSString stringWithFormat:#"%#",object[#"job"];
.
.
.
}
else
{
NSLog(#"Error: %#", [error localizedDescription]);
}
}];
Now you will have object of current user along with its all details. Also you could do a thing, i.e., At time of user filling up profile details save it in a dictionary as below :
NSDictionary *signupDetail = [NSDictionary dictionaryWithObjectsAndKeys:self.userRegisterTextField.text, #"username",
self.nameTextField.text, #"Name",
[ResponseDict objectForKey:#"sessionToken"] ,#"sessionToken",
[ResponseDict objectForKey:#"objectId"], #"objectId",
nil];
//ResponseDict is dictionary you get in response for successful signup.
Then you could store it using [NSUserDefaults standardUserDefaults] so you will have all info of user at one place and call it wherever needed.

iOS-Parse Update row in Classes

i am newbiew in Parse. I'm trying to learn the following this link. https://www.parse.com/docs/ios_guide#objects-updating/iOS
Here is the updated code does not work and creating a new one. This is my code;
PFObject *testObject = [PFObject objectWithClassName:#"TestObject"];
[testObject setObject:#"oldtestobject" forKey:#"testkey"];
[testObject save];
I just want to update the oldtestobject string. Get the new value of newtest.
I'm sorry for my english is bad. I hope what I'm saying.
If you want to update a object with parse, you will first need to create a PFQuery to obtain the object you wish to update, then modify the data, then save the new version. Here is what the sample code may look like:
// Create the PFQuery
PFQuery *query = [PFQuery queryWithClassName:#"TestObject"];
// Retrieve the object by id
[query getObjectInBackgroundWithId:#"oldTestObjectID" block:^(PFObject *pfObject, NSError *error) {
// Now let's update it with some new data. In this case, only cheatMode and score
// will get sent to the cloud. playerName hasn't changed.
[pfObject setObject:#"rowData" forKey:#"columnName"];
[pfObject saveInBackground];
}];

Resources