I have a mutable array named "eventnameArray". What i want is to add objects. This objects to add come from a Parse query.
This is the mutable array:
eventArray = [[NSMutableArray alloc]init];
This is the Parse query, which works.
PFQuery *query = [PFQuery queryWithClassName:#"Event"];
[query selectKeys:#[#"EventName"]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
NSLog(#"Successfully retrieved %lu scores.", (unsigned long)objects.count);
// Do something with the found objects
[eventnameArray addObject:[objects valueForKey:#"EventName"]];
NSLog(#"%#", eventnameArray);
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
I suspect the problem is in the addObject call, which is not being performed correctly, or maybe in the whole PFQuery structure.
To show the array in the tableviewcell, i do this:
cell.label.text = [self.eventnameArray objectAtIndex: [indexPath row]];
EDIT :
I replaced addObject for addObjectsFromArray like this:
[eventnameArray addObjectsFromArray:[objects valueForKey:#"EventName"]];
But i still can't get it to work.
EDIT 2:
I replaced EDIT 1 with :
for (NSObject *object in objects){
NSString *name = [object valueForKey:#"EventName"];
[eventnameArray addObject:name];
}
But the label still doesn't show anything.
EDIT 3 :
The solution was just a matter or reloading data like this:
[self.tableView reloadData];
I guess what you're looking for is to replace addObject: with addObjectsFromArray: because parse returns an array to you so calling valueForKey:#"EventName" will return an array and you want to add all of those names to your eventArray.
So:
[eventnameArray addObjectsFromArray:[objects valueForKey:#"EventName"]];
You probably want to add the EventName of each object in the objects array to your eventnameArray, not the "EventName" value of the objects array.
Try this instead:
for (NSObject *object in objects){
NSString *name = [object valueForKey:#"EventName"];
[eventnameArray addObject:name];
}
//EDIT: Addition for a complete fix. Reload the tabeview afterwards.
[self.tableView reloadData];
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.
i have parse.com database. i have column in a table named "text".
i have to find text with multiple keys matching with AND condition.
i tried it all ways. i tried to use:
PFQuery *query=[PFQuery queryWithClassName:#"post"];
[query whereKey:#"text" containedIn:Array];
or
PFQuery *query=[PFQuery queryWithClassName:#"post"];
[query whereKey:#"text" containsAllObjectsInArray:Array];
or
PFQuery *query=[PFQuery queryWithClassName:#"post"];
for (NSString *str in filtersArray) {
[query whereKey:#"text" containsString:str];
}
but no one works. please guide me if parse sdks supports this or not totally? if yes how can i achieve the results.
many thanks in advance :)
EIDT:
for example i have three entries in database as text:
"i have a data entry"
"i can not find something in data"
"how can i do this"
if pass "i" and "this" it should return entry (3)
if pass "i" and "data" it should return entry (1,2)
if pass "i" and "else" it should return nothing
The reason your query doesn't work is because Parse does not support having the same constraint (in this case 'containsString:') more than once on the same key.
So, what I would suggest is to query for a regular expression which will match all of your filter strings using - (instancetype)whereKey:(NSString *)key matchesRegex:(NSString *)regex.
NSArray *qryStrings = #[str1, str2, str3, ....]; //strings you are trying to match
//string which will hold our regular expression
NSString *regexString = #"^"; //start off the regex
for (NSString *str in qryStrings) { //build the regex one filter at a time
regexString = [NSString stringWithFormat:#"%#(?=.*%#)", regexString, str];
}
regexString = [NSString stringWithFormat:#"%#.*$", regexString]; //finish off the regex
PFQuery *query = [PFQuery queryWithClassName:#"post"];
[query whereKey:#"text" matchesRegex:regexString];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
//objects array contains matching rows with matching strings
}
else {
NSLog(#"%# %#", error, [error userInfo]);
}
}];
Depending on the speed requirements of your query and the number of objects being queried, I would try separating the results using componentsSeparatedByString: after enumerating through the results array using something like: for(NSString *string in results). After separating each string into an individual array, use an if(...) statement that determines if that collection of words contains each word searched.
Code example:
NSMutableArray *searchResults = [[NSMutableArray alloc] init];
PFQuery *query=[PFQuery queryWithClassName:#"post"];
// consider setting a limit, depending on the number of posts
// consider sorting the query as needed
NSArray *posts = [query findObjects];
for(NSString *text in posts)
{
NSArray *words = [text componentsSeparatedByString:#" "]; // use SeperatedByCharactersInSet: for . , or anything else you'd need
switch ([filterArray count])
{
case 1:
if([words containsObject:filterArray[0]])
{
[searchResults addObject:text];
}
break;
case 2:
if([words containsObject:filterArray[0]] &&
[words containsObject:filterArray[1]])
{
[searchResults addObject:text];
}
break;
// case n:
// if([words containsObject:filterArray[0]] &&
// [words containsObject:filterArray[1]] &&
// [words containsObject:filterArray[n]])
// {
// [searchResults addObject:text];
// }
//
// break;
default:
break;
}
_filteredResults = [NSArray arrayWithArray:searchResults]; // local global instance of results - use for maintaining order (be sure to clear it between searches)
The _filteredResults array should be what you're wanting. Be sure to consider speed and the character separators used in the search though.
You simply just need to use whereKey:containsString:
And if you want to use additional parameters, you just simply add a subQuery
Your solution need to modify a bit.
Like this.
PFQuery *query=[PFQuery queryWithClassName:#"post"];
[query whereKey:#"text" containedIn:Array];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
//what your logic you want to write there might comes some records that are counts two times so you can remove those using NSSet
}];
I am currently using parse to develop an iPhone app and I got this code:
I have a Class called "Event" and has a field called "EventName"
PFQuery *query = [PFQuery queryWithClassName:#"Event"];
[query selectKeys:#[#"EventName"]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
NSLog(#"Successfully retrieved %lu scores.", (unsigned long)objects.count);
// Do something with the found objects
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
}
}
}];
This works perfectly, but i get the object's IDs instead of the event names which is what i want.
EDIT :
So far I got this inside the IF statement
self.eventArray = [objects valueForKey:#"EventName"];
for(int i=0; i<10 ; i++){
NSLog(#"%#", eventArray[i]);
}
by doing that the question got solved.
All you have to do is use the objects array that was retuned from finding the objects and pass them into your array by using valueForKey.
So it would be
if (!error) {
self.yourEventNameArray = [objects valueForKey:#"EventName"];
}
I am quering Parse and get an array back
PFQuery *query = [Points query];
[query whereKey:#"city" equalTo:[SharedParseStore sharedStore].chosenCity];
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
I want to sort the array into a dictionary based on the district value that is in the Point object so that i can use a tableview with sections (district section names)
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
for (Points *point in objects) {
[dict setValue:point forKey:point.district];
}
block(dict, error);
} else {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
The problem is it only adds 1 value of course
So to make it easy to understand:
The objects coming from Parse are Point objects with the following property's:
Name,District,City
I want to create a NSdictionary with the districts (so I need to collect them out of the objects first because I don't know them) as a key and the value for that key is an array with the points that are in that district.
I don't know beforehand what the districts will be. They will need to be picked from the objects array that is returned from Parse.
My final object I want to create is a nsdictionary with arrays of points for every distinct district(that is the key).
Example:
[#"districtA" : an array with Point objects that have districtA in their district property, etc etc]
what is the best way to do this because i really can't see how to do it ?
You answered your own question when you say:
I want to create a NSdictionary with the districts as a key and the
value for that key is an array with the points that are in that
district.
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSMutableDictionary *dict = [#{} mutableCopy];
for (Points *point in objects) {
// if no point for that district was added before,
// initiate a new array to store them
if (![dict containsKey:point.district])
dict[point.district] = [#[] mutableCopy];
[dict[point.district] addObject:point];
}
block(dict, error);
} else {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
Im currently using following code to display an array inside of an UItextView / label / textfield :
PFQuery *query = [PFQuery queryWithClassName:#"appMsg"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
NSLog(#"Successfully retrieved %d scores.", objects.count);
// Do something with the found objects
for (PFObject *object in objects) {
NSString *besked = object[#"besked"];
msgRecieved0.text = besked;
NSLog(#"Object values %#",[objects valueForKey:#"besked"]);
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
i have tried to set the NSString to :
NSArray *besked = object[#"besked"];
msgRecieved0.text = besked[0];
msgRecieved1.text = besked[1];
msgRecieved2.text = besked[2];
But again i get an error.
i have tried all i know, and i don't know what i should do to display a "list" of the arrays. I would like to show the first 10 values coming from the array
PFObject will not respond to Dictionary style element addressing. You must use keyValue coding style code.
Instead of NSString *besked = object[#"besked"];, try this:
NSString *besked = [object objectForKey:#"besked"];
Edit - This might be what you need, if the Parse object is an array.
NSArray* besked = [object objectForKey:#"besked"];
NSString* str0 = [besked objectAtIndex:0];
NSString* str1 = [besked objectAtIndex:1];
NSString* str2 = [besked objectAtIndex:2];