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
}];
Related
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
}
I am writing an iOS app and I am using Parse to store data on the server side.
I have Users and each user can have a Car.
I am trying to figure out how to write a query that allows me to get all users that have a car with year less than 2000 and with a certain color (lets say red).
Each car has a relationship to the user and each user also has a relationship to their car.
User <-> Car (one to one)
I started using the PFQuery:
PFQuery * userQuery = [PFQuery queryWithClassName:#"User"];
I am not sure how to handle the relationship in the query. So, I'm pretty much not sure how to get this done.
Any suggestion?
First off, the User class is a special case, when using it in a query you need to do this:
PFQuery *query = [PFUser query];
Next, the way you construct the query you want depends where the pointer is. If the User has a car property that is a pointer to the Car then the query would be as follows:
PFQuery *userQuery = [PFUser query];
PFQuery *carQuery = [PFQuery queryWithClassName:#"Car"];
[carQuery whereKey:#"year" lessThan:#(2000)];
[carQuery whereKey:#"color" equalTo:#"red"];
[userQuery whereKey:#"car" matchesQuery:carQuery];
[userQuery includeKey:#"car"]
[userQuery findObjectsInBackgroundWithBlock:^(NSArray *users, NSError *error) {
for (PFObject *user in users) {
PFObject *car = user[#"car"];
// read user/car properties as needed
}
}];
If instead the Car class has a user property you just do a normal query and add the following line to let you access the full User object:
[carQuery includeKey:#"user"];
What does your table look like? If you have User as a column in your Car table, you can just query the car table for cars of year less than 2000 and then you would just access the User property of that query. It would look something like this:
PFQuery *carQuery = [PFQuery queryWithClassName:#"Car"];
[carQuery whereKey:#"year" lessThan:#(2000)];
[carQuery includeKey:#"user"];
[carQuery findObjectsInBackgroundWithBlock:^(NSArray *cars, NSError *error) {
if (!error) {
for (Car *car in cars) {
User *user = car#["user"];
}
}
}];
I'm building a private chat between 2 users. Currently I've got the "Chat" class open to everyone (read/write) and there is where all messages (objects) go.
I was thinking about adding objects with permission to read only between two users so only they can see what they chat.
I'm grabbing the messages using:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
PFQuery *fquery = [PFUser query]; // query to get the chat partener
[fquery whereKey:#"objectId" equalTo:[[NSUserDefaults standardUserDefaults] stringForKey:#"friendid"]];
PFUser *friend = (PFUser *)[fquery getFirstObject]; // got it!
PFQuery *query = [PFQuery queryWithClassName:#"Chat"]; // new query for grabbing messages
[query whereKey:PF_CHAT_ROOM equalTo:chatroom]; // #"Chat" = #"Chat"
if (message_last != nil) [query whereKey:PF_CHAT_CREATEDAT greaterThan:message_last.date];
[query includeKey:PF_CHAT_USER]; // current user
[query includeKey:[NSString stringWithFormat:#"%#", friend]]; // its friend/partener
[query orderByAscending:PF_CHAT_CREATEDAT]; // sort by date
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
// adding the messages to an array;
}];
For writing messages to parse:
PFObject *object = [PFObject objectWithClassName:#"Chat"]; // class name
object[PF_CHAT_ROOM] = chatroom;
object[PF_CHAT_USER] = [PFUser currentUser];
object[PF_CHAT_TEXT] = text;
PFQuery *query = [PFUser query];
[query whereKey:#"objectId" equalTo:[[NSUserDefaults standardUserDefaults] stringForKey:#"friendid"]];
PFUser *friend = (PFUser *)[query getFirstObject]; // query to get the chat partener
PFACL *roleACL = [PFACL ACL];
[roleACL setReadAccess:YES forUser:[PFUser currentUser]];
[roleACL setReadAccess:YES forUser:friend]; // setting read permission for those guys
object.ACL = roleACL;
[object saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
{
....
}];
Is this the right way to go?
I've implemented a similar app taking the same approach which seemed to work. But I think you've over complicated for what it needs to be.
You need a Chat class which you seem to have. This may be something similar to:
Chat
Object ID, Message, Author, Date, Date Seen, ACL, etc....
(there's many good schemas out there just google it)
Then when you create a new chat message to a friend you simply just create a new PFObject setting the other user's ACL permission to like you've done correctly.
The user can read his messages by calling
PFQuery *query = [PFQuery queryWithClassName:#"Chat"];
The response of the query will only be the chats that the user has read permission to, not everyones. Therefore there's no need to specify any further query parameters unless you're looking for unread messages, etc..
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)
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.