Quite a simple question really but can't find the answer anywhere.
On the Parse data browser, there are lots of users and they each have an array with a bunch of string values, how do i download just one of these arrays from just one user into an NSArray of string values?
Thanks in advance.
Do you know the objectId of the user? or the username? Say it's the username:
PFQuery *query = [PFQuery queryWithClassName:#"User"];
[query whereKey:#"username" equalTo:#"Vladimir Putin"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
if (objects.count) {
PFUser *vladimir = objects[0];
NSLog(#"Putins strings are %#" [vladimir objectForKey:#"theArrayColumn"]);
} else {
// where are you Vlad?
}
} else {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
It's easier if you know the object id. Then use getObjectInBackgroundWithId: instead of find. (To be clear, you'll be downloading the object and it's array property. There's no way that I know of to get just a property).
Related
I have a PFQuery that gets the current participants of a particular event:
PFQuery *getcurrentparticipants = [PFQuery queryWithClassName:#"Event"];
[getcurrentparticipants selectKeys:#[#"Participants"]];
[getcurrentparticipants whereKey:#"objectId" equalTo:ObjectID];
[getcurrentparticipants findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSMutableArray *newParticipantsArray = [[NSMutableArray alloc]init];
if([objects[0] valueForKey:#"Participants"] == nil){ // If object retrieved in objects is null. If there are 0 participants
[newParticipantsArray addObject:PFUser.currentUser.username];
PFQuery *query = [PFQuery queryWithClassName:#"Event"];
[query getObjectInBackgroundWithId:self.ObjectID
block:^(PFObject *Event, NSError *error) {
Event[#"Participants"] = newParticipantsArray;
[Event incrementKey:#"Vacants" byAmount:[NSNumber numberWithInt:-1]];
[Event saveInBackground];
}];
}else{ // STEP 5
for(int i=0;i<objects.count;i++) {
[newParticipantsArray addObject:[[objects objectAtIndex:i] valueForKey:#"Participants"]];
}
[newParticipantsArray addObject:PFUser.currentUser.username];
NSLog(#"Part to upload %#", newParticipantsArray);
PFQuery *query = [PFQuery queryWithClassName:#"Event"];
[query getObjectInBackgroundWithId:self.ObjectID
block:^(PFObject *Event, NSError *error) {
Event[#"Participants"] = newParticipantsArray;
[Event incrementKey:#"Vacants" byAmount:[NSNumber numberWithInt:-1]];
[Event saveInBackground];
}];
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
This is how the method works:
Create a PFQuery object
Query the Participants Class for an specific ObjectId
If no error, then we create a NSMutable array
If no participants are in Parse then we insert the current user as participant.
Else, insert all participants in the mutable array and add currentuser at the end of the array.
Then upload it again to Parse
My problem is in step 5:
When I perform the tasks in the else, the column in Parse looks like this :
[["Participant 1"],"Participant 2"]
But I would like to have it like this:
["Participant 1","Participant 2"]
What I have tried:
I tried things like putting the arrays like this. [newParticipantsArray addObject:[[objects objectAtIndex:i] valueForKey:#"Participants"]]; and similar combinations, of course without luck.
It’s hard to say for sure since I can’t see the structure of your data but are you sure the value held in
[[objects objectAtIndex:i] valueForKey: #“Participants”]
Is a single user and not itself an array of users? The plural key “participants” seems to suggest it’s an array of users which would also explain the result you’re getting.
If in fact the value returned for the "Participants" key is an array, you can add the objects in it to your mutable array by doing the following:
NSArray* participants = [[objects objectAtIndex:i] valueForKey:#"Participants"]
[newParticipantsArray addObjectsInArray:participants];
This uses the addObjectsInArray: method of NSMutableArray to add the objects from the old array into the new one.
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);
}
}];
I've been using sql forever and i'm now stepping into using parse. I've reach a problem regarding the database structure. i have 2 objects called stores and users. i've added the stores objectId to each user so that i can identify which user is to which store. I do not know if there is another way, but this was what i could think of.
The issue is that i want to retrieve all the users and the store names which is connected to the users. How can achieve this using parse?
My code at the moment.
PFQuery *query = [PFQuery queryWithClassName:#"users"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (PFObject *object in objects) {
}
NSLog(#"%#", objects);
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}
It does sound like the aim is to fetch related objects, but my understanding about how to do that differs from #Dima. You do it like this...
PFQuery *query = [PFQuery queryWithClassName:#"users"];
// this tells the query to eagerly fetch the related store object
[query includeKey:#"store"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// handle error, or ...
for (PFObject *object in objects) {
// object is from the users table, and object[#"store"] will contain
// the complete, related store object, eagerly fetched...
NSLog(#"the store object for %# is %#", object, object[#"store"]);
}
}];
If I understand correctly, you just want to fetch a related object? The documentation covers this.
You should be able to fetch a related object like this:
PFObject *store = user[#"store"]; // reference to related object but may need to be fetched
[store fetchIfNeededInBackgroundWithBlock:^(PFObject *object, NSError *error) {
// at this point you have fetched the store or you already have it
NSString *name = store[#"name"];
}];
Working with recipes and I would like to query (search) based off of items in the recipe rather than the recipe names.
For example, multiple items may contain Chicken. I want to be able to search Chicken and see the Recipe Names that contain Chicken in the recipe.
Here's what I have tried:
- (void)filterResults:(NSString *)searchTerm
{
PFQuery * query = [PFQuery queryWithClassName:self.parseClassName];
NSArray * ingredientArray = [self.profileObject objectForKey:#"ingredients"];
[query whereKey:searchTerm containedIn:ingredientArray];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error)
{
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else
{
[self.searchResults removeAllObjects];
[self.searchResults addObjectsFromArray:objects];
[self.searchDisplayController.searchResultsTableView reloadData];
}
}];
}
This code returns nothing and I get no errors.
Having difficulty figuring out the right way to set up the query.
Should this be solved as a query within a query?
Meaning:
Query through ingredients first, and then query on that to display the recipe name based on the previous query of recipes that contain the searchTerm.
I think you are misusing the [query whereKey:containedIn:] method. This is used to query for all PFObjects where the object for the key you specify is contained in the array you provide. Unless you made a new key for every recipe item, this won't work for your purposes, because none of your objects have a "Chicken" key, for instance.
First, I suggest you use a RecipeIngredient class in Parse with the following fields:
Pointer(Recipe) recipe //pointer to its Recipe object
Number amount //how much of unit
String unit //cup, gram, etc.
String ingredient //milk, flour, etc.
Now, you can simply query the RecipeIngredient class like so:
PFQuery * query = [PFQuery queryWithClassName:"RecipeIngredient"];
[query whereKey:"ingredient" equalTo:searchTerm];
[query includeKey:"recipe"]; //Fetches the Recipe data via the pointer
[query findObjectsInBackgroundWithBlock:^(NSArray *recipeIngredientObjects, NSError *error) {
if (!error) {
NSArray *recipes = [recipeIngredientObjects valueForKey:#"recipe"];
//update table data as needed
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
I had this problem last year sometime so I thought I would share the answer.
[query whereKey:#"ingredient" matchesRegex:searchTerm modifiers:#"i"];
That should do it for you. That helps with the case sensitivity.