Parse following PFUser - ios

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.

Related

Having trouble passing PFUser as a PFObject

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

Parse.com Following / Follower Logic

Having some trouble trying to figure out some logic for the following situation.
I have built a friends system for my mobile app using parse. Simply put, when a user "follows" something they are put into a relationship. That relationship contains all of the people that the individual user has folowed.
User
Relationship - Friends (contains all of the users that that overall user has followed)
I can query who an individual user is following fairly easily:
PFQuery *query = [PFUser query];
[query whereKey:#"username" equalTo:#"asg"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
for (PFObject *object in objects) {
PFRelation *friendsRelation = [object objectForKey:#"Friends"];
PFQuery *query = [friendsRelation query];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSLog(#"%#", objects);
} else {
}
}];
}
}];
How would I query who is following a certain user, though? So, a users followers.
If you already know the user, use whereKey:equalTo::
PFObject *user = ...;
PFQuery *query = [PFUser query];
[query whereKey:#"Friends" equalTo:user];
[query findObjectsInBackgroundWithBlock:^(NSArray *results, NSError *error) {
If you need to do a query to get the user then instead combine the requests with whereKey:matchesQuery::
[query whereKey:#"Friends" matchesQuery:userQuery];
I actually did a bunch of blog posts talking about implementing a friends list that might help you:
Overview
JavaScript part 1
JavaScript part 2
JavaScript part 3
The code samples are in JavaScript, but shouldn't be too hard to convert to iOS.
It covers the relationships, querying, updating etc.
The short answer to your question it to use a Join Table instead of a Relation so you can easily query from both sides of the relationship.
You can find a lot of information in the relations guide on the Parse site:
https://parse.com/docs/relations_guide#manytomany-jointables
I think what you are asking for is the PFUser *user = [PFUser currentUser] method. If you are trying to retrieve friends for the current user logged in. You could use the same for retrieving the users that the current user logged in has followed.

Allow only 2 users to read an object from a public class

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..

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
}];

Get a PFUser details who are not current user

I am using the Parse framework and have it set up where I can login and access the user who logs in PFUser object. I want to be able to visit a friends page and to do this i need to query and retrieve data (names and other pieces of information) of a PFUser object which is not the on that is logged in. I cannot find any queries that let me access data from the User class. I hope this makes sense,
Thanks
It really depends on what sort of criteria you want to search on, but you can query PFUsers just like you would any other PFObject within Parse. The only difference is that you create your query with the +[PFUser query] method. Here's an example from Parse's documentation:
PFQuery *query = [PFUser query];
[query whereKey:#"gender" equalTo:#"female"]; // find all the women
NSArray *girls = [query findObjects];
You can also query where a user is an associated object on some other class in Parse, and you can also handle results asynchronously:
PFQuery *query = [PFQuery queryWithClassName:#"Post"];
[query whereKey:#"user" equalTo:user];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// do something with results
}];
Check out the query documentation for other examples of the sorts of things you can do with queries.

Resources