Data from Parse fill table view. When you select a cell turn on a detailed understanding (detailed instructions). There is an update function object (a transition to another controller). The problem is as follows:
When you select a cell with an index of 0 (ie, the first table cell in the list) and further attempt to edit it - an error occurs, the first cell is not updated, and the second. I can not understand what it is connected. And when selecting other cells - objects are updated properly. Can someone faced such problem?
Here's the code:
PFQuery *query = [PFQuery queryWithClassName:#"DATA"];
[query whereKey:#"username" equalTo:[PFUser currentUser]];
[query getObjectInBackgroundWithId:objectId block:^(PFObject *object, NSError *error) {
if (!error) {
object [#"Name"] = name.text;
object [#"Address"] = address.text;
object [#"Date"] = datePicker.date;
[object saveInBackground];
} else {
NSString *errorString = [error userInfo][#"error"];
UIAlertView *error = [[UIAlertView alloc]initWithTitle:#"Oops!" message:errorString delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[error show];
}
}];
Where objectId - ID of the object.
name, adress - UITextField
Your query asks for a user with a username, however you don't give a username as the argument, but a user object.
You should perhaps change your code to
[query whereKey:#"username" equalTo:[PFUser currentUser].username];
Related
I'm trying to query the 'friend' relation while excluding any friends that have blocked the user (which is stored as a relation<_user>) on the friends user with a relation to the user they are blocking (potentially the user checking their friends). I tried querying like below, but it isn't excluding the record like I would think:
[SVProgressHUD showWithStatus:#"Loading ..."];
[friends removeAllObjects];
PFRelation *friendRelation = [[PFUser currentUser] objectForKey:#"friendsRelation"];
if (friendRelation)
{
PFQuery *friendsQuery = [friendRelation query];
[friendsQuery orderByAscending:#"firstname"];
[friendsQuery whereKey:#"disabled" notEqualTo:[NSNumber numberWithBool:YES]];
[friendsQuery whereKey:#"Blocked" notEqualTo:[PFUser currentUser]];
[friendsQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if (!error)
{
friends = [objects mutableCopy];
[self.myTableView reloadData];
[SVProgressHUD dismiss];
}
else
{
[SVProgressHUD showErrorWithStatus:#"Loading failed. Please try again."];
}
}];
}
else
{
[SVProgressHUD dismiss];
}
Is there a way to accomplish what I am trying to do?
I had the same issue in one of my projects and solved it as follows. I created a class "blocked" and once a user blocks another user, I simply create two objects there. I did this in a general helper class, by creating a method (user1 is the current user, user2 is the other user):
void BlockUserOne(PFUser *user1, PFUser *user2)
{
PFQuery *query = [PFQuery queryWithClassName:PF_BLOCKED_CLASS_NAME];
[query whereKey:PF_BLOCKED_USER equalTo:[PFUser currentUser]];
[query whereKey:PF_BLOCKED_USER1 equalTo:user1];
[query whereKey:PF_BLOCKED_USER2 equalTo:user2];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if (error == nil)
{
if ([objects count] == 0)
{
PFObject *object = [PFObject objectWithClassName:PF_BLOCKED_CLASS_NAME];
object[PF_BLOCKED_USER] = [PFUser currentUser];
object[PF_BLOCKED_USER1] = user1;
object[PF_BLOCKED_USER2] = user2;
object[PF_BLOCKED_USERID2] = user2.objectId;
[object saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
{
if (error != nil) NSLog(#"BlockUserOne save error.");
}];
}
}
else NSLog(#"BlockUserOne query error.");
}];
}
This method creates an object in the blocked class, containing the two users that are part of the blocking process, as well as a third field with the user that initially did the blocking. This method is called two times, and user1 is always the current user:
PFUser *user1 = [PFUser currentUser];
BlockUserOne(user1, user2);
BlockUserOne(user2, user1);
This creates two objects in the blocked class (two because this makes handling both users being part of the blocking process easier)
Now, as the objects exist in the blocked class, it's time to check against them when querying for users. Here is an example of searching for users with a search bar:
- (void)searchUsers:(NSString *)search
{
PFUser *user = [PFUser currentUser];
//Querying for users that have been blocked by the current user
//or have blocked the current user (therefore the two different
//objects that I created
PFQuery *query1 = [PFQuery queryWithClassName:PF_BLOCKED_CLASS_NAME];
[query1 whereKey:PF_BLOCKED_USER1 equalTo:user];
//We don't want to query the current user, don't we?
PFQuery *query2 = [PFQuery queryWithClassName:PF_USER_CLASS_NAME];
[query2 whereKey:PF_USER_OBJECTID notEqualTo:user.objectId];
//
//This is the crucial part!!
[query2 whereKey:PF_USER_OBJECTID doesNotMatchKey:PF_BLOCKED_USERID2 inQuery:query1];
//
//
[query2 whereKey:PF_USER_FULLNAME_LOWER equalTo:[search lowercaseString]];
[query2 orderByAscending:PF_USER_FULLNAME];
[query2 setLimit:1000];
[query2 findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if (error == nil)
{
//Do whatever you want to do
}
else //Handle the error
}];
}
First, we query for all the users that have blocked the current user or have been blocked by the current user, and then we search for users that have not been returned by the first query.
This results in query2 returning users that have not been involved in a blocking process with the current user.
Hope this helps clearing up the situation.
I'm trying to get an array with users that the currently logged in user is following, so that I can display them in the UICollectionView.
I've set up an activity class which contains pointers to the users (in "fromUser" and "toUser" columns). I tried then to get data for each user from the User class by using the includeKey method, which doesn't seem to work.
Here's my code:
- (void)queryParseForFollowingUsers {
// Create query for users being followed by the current user
PFQuery *followingUsers = [PFQuery queryWithClassName:#"activity"];
[followingUsers whereKey:#"fromUser" equalTo: [PFUser currentUser]];
[followingUsers whereKey:#"activityType" equalTo:#"follow"];
[followingUsers includeKey:#"toUser"];
[followingUsers findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// For each object from the query
for (PFObject *followedUser in objects) {
PFObject *userData = followedUser[#"toUser"];
// Add object to the array of followedUsers
[profilesArray addObject:userData];
[profilesCollection reloadData];
};
}];
NSLog(#"ARRAY RIGHT AFTER CREATION ######## %#", profilesArray);
}
The weird thing is that an array is not updated with any content when I check its status outside of the block, but when I NSLog it's current content in the loop it returns data just fine. The profilesArray object is defined in .h file.
Does anybody have any clue how to sort out this problem? I would be much obliged for any help.
I cracked it:
- (void)queryParseForFollowingUsers {
// Create query for users being followed by the current user
PFQuery *followingUsers = [PFQuery queryWithClassName:#"activity"];
[followingUsers whereKey:#"fromUser" equalTo: [PFUser currentUser]];
[followingUsers whereKey:#"activityType" equalTo:#"follow"];
[followingUsers includeKey:#"toUser"];
[followingUsers findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// Create an empty array for comparison
NSArray *emptyArray = [[NSArray alloc] init];
if ([objects isEqualToArray:emptyArray]) {
[profilesArray removeAllObjects];
// do something if there are no users followed by the current user
} else {
for (PFObject *followedUser in objects) {
PFObject *userData = followedUser[#"toUser"];
// Add object to the array of followedUsers
[profilesArray addObject:userData];
// Reload the collection view
[self.profilesCollection reloadData];
}
}
} else {
// Show the details of an error if it occurs
[[[UIAlertView alloc] initWithTitle:#"An error occured" message:[NSString stringWithFormat:#"%#", [error userInfo]] delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
}];
}
However simple it may be, I am still struggling to update PFObject data with
-(IBAction)postMessageTapped:(id)sender{
[self hideTextField:_messageTextField];
NSMutableArray *myNewMessageArray=[[NSMutableArray alloc]init];
[myNewMessageArray insertObject:_messageTextField.text atIndex:0];
[myNewMessageArray insertObject:[PFUser currentUser] atIndex:1];
PFQuery *query = [PFQuery queryWithClassName:ClassName];
[query getObjectInBackgroundWithId:currentId block:^(PFObject *object, NSError *error) {
object[messagingArray] = myNewMessageArray;
[object saveInBackground];
}];
}
The intent is to get message string from text field and current user name, and put that into an array which then updates the array that exists on the parse database. However,
Cannot do a comparison query for type: (null)
comes up when the user taps the button that posts the message.
Does anyone have a possible solution?
Edit:
PFQuery *query = [PFQuery queryWithClassName:ClassName];
[query whereKey:#"location" nearGeoPoint:locationOfSelectedPin];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!objects) {
NSLog(#"The getFirstObject request failed.");
} else {
for(PFObject *objectTest in objects){
NSLog(#"Successfully retrieved the object.");
objectTest[#"messagingArray"]=myNewMessageArray;
[objectTest saveInBackground];
}
}
}];
I have also tried using this to update my data, 'successfully retrieved object' gets printed 3 times, but then that is followed by three lines of 'error, object not found for update'.
Check where you are setting objectId - this error means it cannot get the object because you are passing a nil value to the database for lookup.
Here's a bit of code to handle the exception:
if (!currentId) {
NSLog(#"Your currentId object is nil! Check your assignment.");
}
else {
PFQuery *query = [PFQuery queryWithClassName:ClassName];
[query getObjectInBackgroundWithId:currentId block:^(PFObject *object, NSError *error) {
object[messagingArray] = myNewMessageArray;
[object saveInBackground];
}];
}
I'm building an application on Parse.com's backend for iOS that has simple follower / following logic to it. I.e. I want the user to be able to find other users and follow their profiles. I can currently retrieve all of the users in the database using a general PFQuery. Tapping on a users profile image "follows" that person. The data is set up so that an array called isFollowing has a unique object added to it with each new person that the user chooses to follow. It's adding it by the users objectId.
However, here's where my bump in the road is; for a separate screen I only want to return the number of people I, as a user, am following. This is the query to access the data:
- (void)viewDidAppear:(BOOL)animated
{
PFQuery *followingQuery = [PFUser query];
[followingQuery whereKey:#"objectId" equalTo:[PFUser currentUser].objectId];
[followingQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error)
{
NSLog(#"User test: %#", [objects valueForKey:#"isFollowing"]);
PFQuery *imagesQuery = [PFUser query];
[imagesQuery whereKey:#"objectId" containedIn:[objects valueForKey:#"isFollowing"]];
[imagesQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if (!error)
{
NSLog(#"Username? %#", [objects valueForKey:#"username"]);
}
else
{
NSLog(#"Something went wrong. %#", error);
}
}];
}
else
{
NSLog(#"Something went wrong: %#", error);
}
}];
[super viewDidAppear:animated];
}
Currently, user test: %# gives the output:
2014-07-28 10:17:58.537 YouStreamSport[11276:60b] User test: (
(
bHul1vkkmB,
brsN8PRUBO
)
)
However, when I run objects.count it's returning one object. Because of this I'm unable to iterate through the array object to find and return only the proper profile images. Since the array object is returning as 1, but there are 2 objects in the array itself, how can I access the items in that array? Any attempts to access using [objectAtIndex: ...] result in a crash.
Thanks for the input in advance.
I wasn't sure how to access a single item in an array within an array, but thanks to the help of #Droppy, I was able to solve the problem. This is the code I am now using:
- (void)viewDidAppear:(BOOL)animated
{
PFQuery *followingQuery = [PFUser query];
[followingQuery whereKey:#"objectId" equalTo:[PFUser currentUser].objectId];
[followingQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error)
{
self.array = [objects valueForKey:#"isFollowing"];
NSLog(#"User test: %#", self.array);
for (int i = 0; i <= self.array.count; i++)
{
NSLog(#"User %d: %#", i, [[[objects valueForKey:#"isFollowing"] objectAtIndex:0] objectAtIndex:i]);
}
}
else
{
NSLog(#"Something went wrong: %#", error);
}
}];
[super viewDidAppear:animated];
}
The resulting output is as follows:
2014-07-28 10:53:16.155 appName[11416:60b] User 0: bHul1vkkmB
2014-07-28 10:53:16.156 appName[11416:60b] User 1: brsN8PRUBO
Thank you!
As written you will only display one objects username. Instead of trying to access them by index try iterating through the results like below. I'd also recommend not using the variable objects for both the inner and outer query. Try this out:
[imagesQuery findObjectsInBackgroundWithBlock:^(NSArray *myObjects, NSError *error)
{
if (!error){
if (myObjects.count) {
for (PFObject *item in myObjects){
NSLog(#"Username: %#", [item valueForKey:#"isFollowing"]);
}
}
}else{
NSLog(#"Something went wrong. %#", error);
}
}];
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.