Parse.com - Getting pointer data contained in [PFUser currentUser] - objective-c

I am using the Parse.com iOS SDK, and I don't know what method I need to call to make sure that the PFUser currentUser contains the data for each pointer contained in it. It is probably very simple, but, as a beginner with this platform, I cannot find a solution.
Just to clarify, I am trying to get the username item in the following. It looks like it is always null, even though I am calling [[PFUser currentUser] fetchIfNeeded] before proceeding:
[[[PFUser currentUser] objectForKey:#"partner"] objectForKey:#"username"];
Thank you,
Andrea

You can do it in a single query by using includeKey:
PFQuery *query = [PFUser query];
[query includeKey:#"partner"];
[query includeKey:#"anotherPointerColumnName"];
[query getObjectInBackgroundWithId:[[PFUser currentUser] objectId]
block:^(PFObject *populatedUser, NSError *error) {
PFObject *partner = populatedUser[#"partner"];
PFObject *another = populatedUser[#"anotherPointerColumnName"];
}];
You can also use deeper levels, so if partner contained a pointer in it you needed called deeperPointerColumnName:
[query includeKey:#"partner.deeperPointerColumnName"];
Then in your completion block you can read it after you get the partner:
PFObject *partner = populatedUser[#"partner"];
PFObject *deeper = partner[#"deeperPointerColumnName"];

Well, I found a workaround by myself. It looks like the solution is to call the fetch method on the pointer before proceeding:
[[[PFUser currentUser] objectForKey:#"partner"] fetch];
If there is a cleaner and swifter way of doing it (automatically for instance) I would really appreciate any advice.

Related

Parse.com combine nested query

I am new to using parse, and currently adding parse to an app that uses SOAP web services to replace them.
Now I come a little stuck, as due to having it done in MySQL and php I am trying to translate the logic from the tables and code to parse.
I have a function that I have written and it achieves exactly what I am after, however I just think its wrong and can be done better, for starters I am not calling findObjectsInBackground, which I know I need to.
I am trying to take this result and then reload a tableView.
NSMutableArray *activityfeed = [NSMutableArray new];
//get current user
PFUser *user = [PFUser currentUser];
if (user != nil) {
PFQuery *query = [PFQuery queryWithClassName:#"Event"];
//get event that user is involved in
[query whereKey:#"invited" equalTo:user];
//get the events
NSArray *events = [query findObjects];
//loop over the events
for (PFObject *event in events) {
//owner is a pointer to the users class
PFUser *owner = event[#"owner"];
if (![user.objectId isEqualToString:owner.objectId]) {
//ignore the info for the logged in user for now
//invited is a relation so one event has many users
PFRelation *relation = [event relationForKey:#"invited"];
PFQuery *query = [relation query];
[query orderByDescending:#"dateinvited"];
[query addDescendingOrder:#"dateaccepted"];
//get the friends that are involved with the event
NSArray *friends = [query findObjects];
for (PFUser *friend in friends) {//Perform logic checks here and then add to activityfeed}
}
}
}
return activityfeed;
So my logic above gets the current user, then get all the events that user is involved with, then get all the other people involved with that event and then work out what to display.
Is there a more efficient way of doing the above?
Usually we use whereKey:matchesQuery in cases like this. Take some research on this.
This question may help you find out some solution.

Correct way to user PFQuery to query relational data like Pointer

Ok so let's say I have a post of an event, and users can click a button to notify that they are attending this event. As of now I have a class called Activity in which I save the current user and the event to this class, so theres 2 columns. If I want to query all users who are attending an event, am I headed in the right direction to do this, or am I doing it complentely wrong?
So far I have:
-(PFQuery*)queryForTable {
PFQuery *activityQuery = [PFQuery queryWithClassName:#"Activity"];
[activityQuery whereKey:#"event" equalTo:self.event];
[activityQuery includeKey:#"going"];
return activityQuery;
}
cellForRowAtIndex:
UILabel *title = (UILabel*) [cell viewWithTag:1];
title.text = [object objectForKey:#"going.username"];
You can actually see what you have been done in the Parse dashboard. That's also their purpose to develop a data browser like this. It's way more convenient.
For your case, you just need to check whether the type is Pointer. Try to click on that if so in the dashboard. It will direct you to the target object.
Would suggest you to read this article first, it's about the relation:
https://parse.com/docs/relations_guide
Then, you should go check the iOS SDK tutorial:
includeKey is definitely what you need to use.
Here is the sample from Parse:
PFQuery *query = [PFQuery queryWithClassName:#"Comment"];
// Retrieve the most recent ones
[query orderByDescending:#"createdAt"];
// Only retrieve the last ten
query.limit = 10;
// Include the post data with each comment
[query includeKey:#"post"];
[query findObjectsInBackgroundWithBlock:^(NSArray *comments, NSError *error) {
// Comments now contains the last ten comments, and the "post" field
// has been populated. For example:
for (PFObject *comment in comments) {
// This does not require a network access.
PFObject *post = comment[#"post"];
NSLog(#"retrieved related post: %#", post);
}
}];
Your code looks right on so far. Then to retrieve your Activity class values, you can use:
PFQuery *activityQuery = [PFQuery queryWithClassName:#"Activity"];
// Set contraints here, example:
[activityQuery setLimit:100];
[query findObjectsInBackgroundWithBlock:^(NSArray *array, NSError *error) {
if (!error) {
// Success, do something with your objects.
}
}];

parse.com API - how to run a query inside parse classes files?

I will try to explain myself as best as I can.
My app has a login & sign Up using the Parse API .
after signing or logging the User see a page with a Button and a Text Field which he can write Numbers in it ,
let's say he write , for example: 1234.
the button job is to save the data from the text field
Now i'm sure my Button method isn't the best way, but it's work :-)
NSString *whoIsTheUser = [PFUser currentUser];
NSString *phoneNumbers = phoneNumberField.text ;
NSString *fullData = [NSString stringWithFormat:#" %# , %#", whoIsTheUser, phoneNumbers];
NSLog(#" %#, %# ", whoIsTheUser, phoneNumbers);
PFObject *addValues= [PFObject objectWithClassName:#"phoneNumber"];
[addValues setObject: fullData forKey:#"numbers"];
[addValues saveInBackground];
So now what i'm having is the data saved to parse site under class of Numbers (forKey:#"numbers")
and it's look like this :
<PFUser:hqExhaYaIN:(null)> {email = "buffo#yahoo.com";username = buffo;} , 1234
what I'm trying to do is to add another button which going to check if theres another user
who wrote the same numbers and then send an alert or do something .
I have tried to read about the PFQuery but didn't find any solution.
is it even possible to run Query in the classes name ? or maybe theres another way to do it ( within the parse site ) ?
thank you so much for any suggestion !
It looks like you need to split up fullData in your parse objects and do something like this
PFQuery* numQuery = [PFQuery queryWithClassName:#"phoneNumber"];
[numQuery whereKey:#"numbers" equalTo:phoneNumbers];
[numQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if(!error)
{
for(PFObject *numObject in objects)
{
//Do what you need to do here
}
}
else
{
//handle error
}
}
EDIT - this means you would save your PFObjects like this
PFObject *addValues= [PFObject objectWithClassName:#"phoneNumber"];
[addValues setObject: phoneNumbers forKey:#"numbers"];
[addValues setObject: whoIsTheUser forKey:#"theUser"];
[addValues saveInBackground];
i hope it's going to help someone like it's helps me , if you want to query for info without the user info use those lines
PFQuery* numQuery = [PFQuery queryWithClassName:#"phoneNumber"];
[numQuery whereKey:#"numbers" equalTo:phoneNumbers];
[numQuery whereKey:#"theUser" notEqualTo:[PFUser currentUser]];
[numQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
all I had to do is add notEqualTo and CurrentUser :-)

Parse query always true

Perhaps this is not the right place for this, but I am sure that many users here are familiar with Parse framework for iOS. Basically I am having issues with a query, all I want to do is check if a username already exists (they do so at login) except I need to do it in order to set up a relationship between the current user and another user. Currently my method is:
PFQuery *query = [PFUser query];
[query whereKey:#"username" equalTo:username.text];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSLog(#"query returned with result");
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
}
}
else {
NSLog(#"Nope");
}
}];
username is just a string containing the word entered in plain text from UITextField. But no matter what I put in, the query seems to go through and I get a message of success. I even tried iterating through the objects as shown in the for loop and I get nothing logged. What is going on here?
EDIT
Just for clarification, username is simply taken from a IBOutlet UITextField *username from the view controller which takes in the username from input. I have tested to make sure that it is being taken correctly. If I enter "foo", I can log the username.text and it will be "foo", however I have no registered users named "foo" so I do not understand why the query is returning without error.
You will get message of success even there is no object found.
(Try log objects.count)
If so, you should check your spelling on Key Value or Query Value.
They are case-sensitive.

What happens if you try to save a PFObject that has been removed by another user?

In my game I have a situation where the player can download a PFObject, and then make changes to it, however that PFObject on the server might be removed by another player, what would then happen if the original player then does a save command on that object? would it crash because it no longer exists on the server? would it create a new object with the same original data? ideally I want nothing to happen, but if there is an issue, is it possible to check if the PFObject still exists on the server before doing the save?
I have used Parse for a while, and I think the "Save" operation will create a new object.
To prevent this, just like you said to fetch the object see if it still exists:
PFQuery *query = [PFQuery queryWithClassName:#"YourClassName"];
[query getObjectInBackgroundWithId:theObject.objectId block:^(PFObject *object, NSError *error) {
if(object) {
// object exists then do the Save
}
}];