I'm developing an iOS app to parse data
I have a class called #"name" this class contains a string column [name]
and a class called #"email" this class contains a string column[email]
the class are already related and no have problem with that
In a different ViewController have two TextField and one button, on a TextField the user enters a valid name string (name)
The button display should show in the second TextField the email associated with the name entered. I want to associate this data.
//relation class
PFObject *data = [PFObject objectWithClassName:#"nameContactMe"];
data[#"name"] = _name.text;
PFObject *DataRequest = [PFObjec objectWithClassName:#"mailContactMe"];
DataRequest[#"email"] = _email.text;
DataRequest[#"relation"] = data;
[DataRequest saveInBackground];
here the disaster
//get relation
- (IBAction)GetDate:(id)sender {
PFRelation *relation = [user relationForKey:#"relation"];
[user saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (succeeded) {
// The post has been added to the user's likes relation.
} else {
// There was a problem, check error.description
}
}];
PFObject *data = _Visitor.text = #"relation";
[data fetchIfNeededInBackgroundWithBlock:^(PFObject *post, NSError *error) {
emailField.text = data[#"email"];
// do something with your title variable
}];
}
I think you should use PFQuery for fetching the desired email :
PFQuery *query = [PFUser query];
[query whereKey:#"name" equalTo:name];
[query getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
NSString *email = [object valueForKey:#"email"];
}
If you want to fetch the email of current user(Logged in user) then you can use this :
NSString *email =[[PFUser CurrentUser] [#"email"];
Related
My situation includes having PFObjects that are connected with relations and I want to add to the relation using the local datastore.
So, I have a screen that creates a main object and saves it to the data store and server properly like so:
// Save User
PFObject *parseUser = [PFObject objectWithClassName:#"Users"];
parseUser[#"name"] = name;
parseUser[#"uuid"] = userUuid;
[parseUser saveEventually];
// Save List
PFObject *parseList = [PFObject objectWithClassName:#"Lists"];
parseList[#"name"] = newList.listName;
parseList[#"uuid"] = newList.listUuid;
[parseList saveEventually];
[parseUser pinInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (succeeded) {
// Create relation
PFRelation *relation = [parseUser relationForKey:#"listAccess"];
[relation addObject:parseList];
[parseUser saveEventually];
}
}];
[parseList pinInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (succeeded) {
// Create relation
PFRelation *relation = [parseList relationForKey:#"sharedWith"];
[relation addObject:parseUser];
[parseList saveEventually];
}
}];
So this part works. This took me a bit to figure out as well, but it works. Creates the User and List. Sets the relations of both then saves. Easy.
On to the problem area:
// Save List
PFObject *parseList = [PFObject objectWithClassName:#"Lists"];
parseList[#"name"] = newList.listName;
parseList[#"uuid"] = newList.listUuid;
[parseList saveEventually];
PFQuery *query = [PFQuery queryWithClassName:#"Users"];
[query fromLocalDatastore];
[query whereKey:#"uuid" equalTo:[User instance].userUuid];
[[query findObjectsInBackground] continueWithBlock:^id(BFTask *task) {
if (task.error) {
NSLog(#"Error: %#", task.error);
return task;
}
PFObject *user = [task.result objectAtIndex:0];
// Create relation
PFRelation *relation = [user relationForKey:#"listAccess"];
[relation addObject:parseList];
[user saveEventually];
PFQuery *relationQuery = [relation query];
[[relationQuery findObjectsInBackground] continueWithBlock:^id(BFTask *task) {
NSLog(#"resutls: %#", task.result);
return task;
}];
[parseList pinInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (succeeded) {
// Create relation
PFRelation *relation = [parseList relationForKey:#"sharedWith"];
[relation addObject:user];
[parseList saveEventually];
}
}];
return task;
}];
So what I am thinking I am doing here is grabbing the user from the local data store and adding another relation to it. But in reality, this actually is only saving the parseList to user relation. User doesn't get changed in the datastore or the server.
Other things I've tried:
Querying just the server
Pinning the User object with a name
EDIT: includeKey (This doesn't work as the include isn't a PFObject.)
Thanks for the help in advance.
Edit:
Looking through the query and relation grabs I get some weird data information.
So, first off, the relation is empty when searching through it like so:
estimatedData
0 - name - Bill Nye
1 - listAcces - no summary
value - PFRelation
knownObjects - 0 objects
2 - uuid - long string that is uuid
So this matches the server stuff, all besides the relation. But, when I query the relation and log it, I get this:
resutls: (
" {\n name = Okkkkk;\n sharedWith = \" Users>\";\n uuid = \"D8174D80-4F08-4B25-9B72-F8E00CF19DDB\";\n}"
)
So querying it, it is there, but it doesn't exist to the relation?
I have a Follower class where stores all following/follower relations of my app. However, when I was trying to retrieve the pointer of each PFUser, I can't get the attributes of each PFUser. Here is my code
PFQuery *query = [PFQuery queryWithClassName:#"Follower"];
[query whereKey:#"from" equalTo:[PFUser currentUser]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if (!error)
{
for(PFObject *o in objects)
{
PFUser *otherUser = (PFUser *)[o objectForKey:#"to"];
NSLog(#"%#",otherUser);
NSLog(#"%#",otherUser.username);
NSString *nickName = otherUser[#"nickName"];
cell.friendNameLabel.text = nickName;
NSLog(#"%#", otherUser[#"nickName"]);
//cell.friendUsrnameLabel.text = otherUser.username;
PFFile *imgFile = otherUser[#"profilePhoto"];
profileView.file = imgFile;
[profileView loadInBackground];
}
}
else
{
NSLog(#"error");
}
}];
when I tried to print every user, here is what i got from the console:
<PFUser: 0x7fc102ec9f70, objectId: GiOIGiNHjK, localId: (null)> {
}
so it didn't find the attributes of each user. Anyone knows the solution? Thanks.
Try to add this line before executing the query.
[query includeKey:#"to"];
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 );
}
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.
I play around with parse.com
For my little project I wanna download an Integer from Parse User Class (_User) in to a float.
How would I do that?
I tried with that code:
PFQuery *updatingQuery = [PFUser query];
[updatingQuery whereKey:#"objectId" equalTo:objectID];
[updatingQuery getFirstObjectInBackgroundWithBlock:^(PFObject * updating, NSError *error)
{
if (!error)
{
myFloat = [EXPData valueForKey:#"Data"];
}
}];
But I will become an error:
Assigning to 'float' from incompatible type 'id'
How can I retrieve a float?
Basically do the opposite of uploading after you retrieve the object:
PFQuery *updatingQuery = [PFUser query];
[updatingQuery whereKey:#"objectId" equalTo:objectID];
[updatingQuery getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (!error) {
int someNumber = object[#"IntegerClass"];
self.someLabel.text = [NSString stringWithFormat:#"%d", someNumber];
}
}];
Please read through Parse docs before asking something fundamental, or show that you've exercised some research. This is a fundamental basic of Parse query:
Here are some key sites you should bookmark if you plan on being a Parse developer:
https://parse.com/docs/ios/api/
https://www.parse.com/docs/ios/guide#push-notifications
https://www.parse.com/docs/ios/guide
https://parse.com/docs/downloads