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
Related
I'm trying to make a follow action with parse on my ios9 project but i have a little problem when retreiving the PFUser from parse using objectId can anyone help me please (the problem is in adding the user ID of current user to the user followed )
- (IBAction)followButtonAction:(id)sender {
PFQuery * query = [PFUser query];
[query whereKey:#"objectId" equalTo:_a.userId];
NSArray *objects = [query findObjects];
PFUser *user= objects.firstObject;
//add the user ID for the cell we are following to the array of followed items in the user class in parse
[[PFUser currentUser] addUniqueObject:_a.userId forKey:#"followed"];
[[PFUser currentUser] saveInBackground];
//add the user ID to the user that the user followed
[user addUniqueObject:[PFUser currentUser].objectId forKey:#"followers"];
[user saveInBackground];
}
Assuming your question is about the long-running operation (as per your comment):
Your query is being executed on the main thread, because you called [query findObjects]. Use findObjectsInBackgroundWithBlock instead, and place all the code after that inside the callback.
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!
How would I go about displaying a list of all users in the parse.com database in a tableview and then when they click on each table, display that particular user's information.
All I know is that in order to query the users I must use:
PFQuery *query = [PFUser query];
Thank you in advance and any help is much appreciated.
You're really asking a specific question about Parse queries, but it seems like you don't understand queries in general, so just start with a general query against Parse:
PFQuery *query = [PFQuery queryWithClassName:#"_User"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
// Something went wrong
} else {
// objects is an array of PFObject containing your results
}
}];
As you figured out, you can also do a user query by making that first line:
PFQuery *query = [PFUser query];
The rest is the same.
Lyndsey Scott is right, this is basic stuff in the docs. I'm posting this here because of the one "gotcha" which is the class name (_User instead of User) if you use the first method.
What you generally will do is call [myTableView reloadData] inside the success block since you now have an array of users. In your didSelectCellAtIndexPath: perform a seque with a new viewcontroller, and in your prepareForSegue method, pass the user object to your pushed view controller so it knows what user to show.
I assume you know how to use table view. So I'll implement it this way:
1.create a property
#property (nonatomic) NSArray *users;
2.In viewDidAppear execute the query:
PFQuery *query = [PFUser query];
[query setLimit:1000];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
self.users = objects;
[self.tableView reloadData];
}
}];
3.You need to implement table view code, the most important is cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"userCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
PFUser *user = self.users[indexPath.row];
cell.textLabel.text = user.username;
return cell;
}
Beside that you also need all of the required table view's data source code to tell it the number of cell. If you'll need some help with that just tell.
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
}];
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.