Here's my code for returning a unique value for identical keys in a dictionary. Right now, in my log, my "objects array:" is 6 (3 sets of (2 objects with identical keys)), and my "dictionary:" returns values for 1 object from each set (3 unique values). In my 'for' statement:
for (id key in dict)
{
self.titlesArray = [NSMutableArray arrayWithObject:dict];
NSLog(#"titles: %#", self.titlesArray);
self.titlesArray = [[NSMutableArray alloc] initWithObjects:[dict valueForKey:key] ,nil];
NSLog(#"titles: %#", self.titlesArray);
}
The first log prints out the three unique values AND keys. The second prints only a single value for a single key (which is what I want.. but I need all three key values) So my problem now is that I am unable to pull a key for each unique value from the dictionary and add it to my titlesArray.
for (id key in dict)
{
self.titlesArray = [NSMutableArray arrayWithObject:dict];
self.titlesArray = [[NSMutableArray alloc] initWithObjects:[dict valueForKey:key] ,nil];
code isn't quite right.
PFQuery *query = [PFQuery queryWithClassName:#"Images"];
[query whereKey:#"recipientIds" equalTo:[[PFUser currentUser] objectId]];
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else {
// found messages!
self.objectsArray = objects;
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for(id obj in self.objectsArray){
PFObject *key = [obj valueForKey:#"titleLabel"];
if(![dict objectForKey:key]){
[dict setValue:key forKey:[obj valueForKey:#"titleLabel"]];
}
}
for (id key in dict) {
self.titlesArray = [NSMutableArray arrayWithObject:dict];
NSLog(#"titles: %#", self.titlesArray);
self.titlesArray = [[NSMutableArray alloc] initWithObjects:[dict valueForKey:key] ,nil];
NSLog(#"titles: %#", self.titlesArray);
}
NSLog(#"dictionary: %#", dict);
NSLog(#"Objects array is %d", [self.objectsArray count]);
[self.pickerView reloadComponent:0];
it looks like there is some type error in line
PFObject *key = [self.objectsArray valueForKey:#"titleLabel"];
it should be
PFObject *key = [obj valueForKey:#"titleLabel"];
It's happening in this line, isn't it:
if(![dict objectForKey:#"titleLabel"]){
[dict setValue:obj forKey:key];
}
}
You are setting "obj" as a value, no problem there, but then you are using "key" which is a PFObject, but NSDictionary requires a NSString for the key.
If PFObject contains a NSString property that you want to use, you can pass that in. For example, if PFObject has an NSString property called "name" you could call this:
if(![dict objectForKey:#"titleLabel"]) {
[dict setValue:obj forKey:key.name];
}
}
The relevant thing to notice is the types of the parameters when NSMutableDictionary defines this method, namely the (NSString*):
- (void)setValue:(id)value forKey:(NSString *)key
How does your PFObject look like. Does it have strings in it?. According to your question you already know that you can't pass a PFObject as key for dictionary. If your object is some what like this
interface PFObject : NSObject
{
NSString *keyString;
......
.Some other variables
}
Then you should be using it like this to set it as key
PFObject *key = [self.objectsArray valueForKey:#"titleLabel"];
if(![dict objectForKey:#"titleLabel"]){
[dict setValue:obj forKey:[key valueForKey#"titleLabel"]];
}
Here is the code I found to work. It takes the array and sorts through the keys to return only unique values for a specific key:
PFQuery *query = [PFQuery queryWithClassName:#"Images"];
[query whereKey:#"recipientIds" equalTo:[[PFUser currentUser] objectId]];
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else {
// found messages!
self.objectsArray = objects;
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for(id obj in self.objectsArray){
PFObject *key = [obj valueForKey:#"titleLabel"];
if(![dict objectForKey:key]){
[dict setValue:key forKey:[obj valueForKey:#"titleLabel"]];
}
}
for (id key in dict) {
self.titlesArray = [NSMutableArray arrayWithObject:dict];
[self.titlesArray addObject:dict.allKeys];
self.titlesArray = [self.titlesArray objectAtIndex:1];
}
NSLog(#"titles: %#", self.titlesArray);
[self.pickerView reloadComponent:0];
Related
I am trying to create a NSMutableArray which will become the dataSource for a UIPickerView, but nothing is getting added to the array, the console just shows (. What am I doing wrong?
NSMutableArray *arr = [[NSMutableArray alloc] init];
PFQuery *rejectedNumber = [PFQuery queryWithClassName:#"Group"];
[rejectedNumber findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!objects) {
// Did not find any UserStats for the current user
NSLog(#"NotFound");
} else {
for (int i=0;i<[objects count];i++)
{
PFObject * obj = [objects objectAtIndex:i];
self.theObject = obj;
NSString *string = obj[#"GroupName"];
[arr addObject:string];
NSLog(#"GOGOGO%#", arr);
}
How can I combine multiple Parse Queries?
I want to query the column sclink and songTitle from parse.com then add each to its own array.
Also how to save query locally and call it? IF else statment or something:
NSMutableArray *trackList = [[NSMutableArray alloc] init];
PFQuery *queryTracks = [PFQuery queryWithClassName:#"liveRadioPL"];
NSArray *objects = [queryTracks findObjects]; // Online PFQuery results
[PFObject pinAllInBackground:objects];
[queryTracks selectKeys:#[#"scLink"]];
[queryTracks findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
totalTracks = (int)objects.count;
NSLog(#"Successfully retrieved %lu Tracks.", (unsigned long)objects.count);
// Do something with the found objects
for (PFObject *object in objects) {
[trackList addObject:[NSString stringWithFormat:#"%#", [object objectForKey:#"scLink"]]];
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
trackListArray = trackList;
NSMutableArray *trackTitles = [[NSMutableArray alloc] init];
PFQuery *queryTitles = [PFQuery queryWithClassName:#"liveRadioPL"];
NSArray *objectsTitle = [queryTitles findObjects]; // Online PFQuery results
[PFObject pinAllInBackground:objects];
[queryTracks selectKeys:#[#"songTitle"]];
[queryTracks findObjectsInBackgroundWithBlock:^(NSArray *objectsTitle, NSError *error) {
if (!error) {
// The find succeeded.
totalTitles = (int)objectsTitle.count;
NSLog(#"Successfully retrieved %lu Titles.", (unsigned long)objectsTitle.count);
// Do something with the found objects
for (PFObject *object in objects) {
[trackTitles addObject:[NSString stringWithFormat:#"%#", [object objectForKey:#"songTitle"]]];
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
I'm not sure your logic really makes sense - you're using 4 API requests when all you need is 1 API request. Also, Jacob is right, you're filling an array from a background thread and as a result the main thread will see it as empty.
I think I understand what you're trying to do - try this
PFQuery *queryTracks = [PFQuery queryWithClassName:#"liveRadioPL"];
// use includeKey if slink and songTitle are pointers to other Parse classes
// from the context of your question you probably don't need to use includeKey
[queryTracks includeKey:"scLink"];
[queryTracks includeKey:"songTitle"];
NSArray *objects = [queryTracks findObjects];
NSMutableArray* scLinks = [[NSMutableArray alloc] init];
NSMutableArray* songTitles = [[NSMutableArray alloc] init];
for (PFObject* object in objects) {
[scLinks addObject:object[#"scLink"]];
[songTitles addObject:object[#"songTitles"]];
}
I hope this helps, good luck!
I run a Parse query in my iOS app TableViewController.m.
I need to ask the iOS app for that query data from my WatchKit extension InterfaceController.m
How would I go about this using openParentApplication(_:reply:) + handleWatchKitExtensionRequest(_:reply:)?
TableViewController.m (iOS)
- (void)viewDidLoad {
// GMT Date from Phone
NSDate *gmtNow = [NSDate date];
NSLog(#"GMT Now: %#", gmtNow);
// Query Parse
PFQuery *query = [self queryForTable];
[query whereKey:#"dateGame" greaterThanOrEqualTo:gmtNow];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSMutableArray *localMatchup = [#[] mutableCopy];
for (PFObject *object in objects) {
// Add objects to local Arrays
[localMatchup addObject:[object objectForKey:#"matchup"]];
// App Group
NSString *container = #"group.com.me.off";
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:container];
// Matchup
[defaults setObject:localMatchup forKey:#"KeyMatchup"];
NSArray *savedMatchup = [defaults objectForKey:#"KeyMatchup"];
NSLog(#"Default Matchup: %#", savedMatchup);
savedMatchup = matchupArray;
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
}];
}
AppDelegate.m (iOS)
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply {
NSString * request = [userInfo objectForKey:#"requestString"];
if ([request isEqualToString:#"executeMethodA"]) {
// GMT Date from Phone
NSDate *gmtNow = [NSDate date];
NSLog(#"GMT Now: %#", gmtNow);
// Query Parse
PFQuery *query = [self queryForTable];
[query whereKey:#"dateGame" greaterThanOrEqualTo:gmtNow];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSMutableArray *localMatchup = [#[] mutableCopy];
for (PFObject *object in objects) {
// Add objects to local Arrays
[localMatchup addObject:[object objectForKey:#"matchup"]];
// App Group
NSString *container = #"group.com.me.off";
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:container];
// Matchup
[defaults setObject:localMatchup forKey:#"KeyMatchup"];
NSArray *savedMatchup = [defaults objectForKey:#"KeyMatchup"];
NSLog(#"Default Matchup: %#", savedMatchup);
savedMatchup = matchupArray;
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
reply(#{#"success:": #true});
}
}];
}
// Assuming this is where I'd do the reply?
// Not sure what would go here for the reply though?
reply(#{#"success:": #false});
}
InterfaceController.m (WatchKit)
NSString *requestString = [NSString stringWithFormat:#"executeMethodA"]; // This string is arbitrary, just must match here and at the iPhone side of the implementation.
NSDictionary *applicationData = [[NSDictionary alloc] initWithObjects:#[requestString] forKeys:#[#"theRequestString"]];
[WKInterfaceController openParentApplication:applicationData reply:^(NSDictionary *replyInfo, NSError *error) {
// What would I put here?
NSLog(#"\nReply info: %#\nError: %#",replyInfo, error);
}];
I'm using Objective-C. Will add any extra info needed, thanks!
Make the Parse query in your AppDelegate method and package it in an NSDictionary and call reply(queryDict); The replyInfo dictionary in your InterfaceController will be populated with queryDict.
I have UITableView with data taken from Parse.com. When I tried to filter them according to the NSArray, it does not show any results. Without the whereKey:containedIn, everything works fine. NSArray *array returns array of strings well. So the problem must be in the method containedIn, any ideas?
PFUser *user = [PFUser currentUser];
NSArray *array = [[PFUser currentUser] objectForKey:#"favorites"];
NSLog(#"ARR:%#", array);
if (user) {
quer = [PFQuery queryWithClassName:#"bs"];
[quer whereKey:#"objectId" containedIn:array];
[quer findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
self.itemss = [objects mutableCopy];
NSLog(#"KOL::%lu", (unsigned long)[objects count]);
[self.MainTable reloadData];
if (objects.count ==0) {
} else {
}
} else {
[quer cancel];
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
} else {
NSLog(#"no");
}
}
The array of "favorites" is an array of favorite objects when I'm sure it should be an array of objectIds. If you create an array that contains the objectIds of the favorite objects then it should work.
I have an array of objects(images) with key values of #"titleLabel" stored on a backend server(parse). What I am trying to do is display the list of titles in a pickerView but I only want to display ONE title for every group of #"titleLabels" whose keys match. For example: if I have five objects(images) with titleLabel key: 'Spring Break' I only want to display one instance of the title 'Spring Break' and not all five. The code I have written is my best amateur shot at solving it but my NSLog for 'titles array count' is returning a value of 1 and when I log the value I get all of the titles again.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
PFQuery *query = [PFQuery queryWithClassName:#"Images"];
[query whereKey:#"recipientIds" equalTo:[[PFUser currentUser] objectId]];
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for(id obj in self.objectsArray){
PFObject *key = [self.objectsArray valueForKey:#"titleLabel"];
if(![dict objectForKey:key]){
[dict setValue:obj forKey:key];
}
}
for (id key in dict) {
NSLog(#"key: %#, value: %# \n", key, [dict objectForKey:key]);
NSLog(#"Objects array is %d", [self.objectsArray count]);
NSLog(#"Titles array is %d", [self.titlesArray count]);
}
[self.pickerView reloadComponent:0];
}
}];
And here is where I define my keys in a separate controller:
PFObject *image = [PFObject objectWithClassName:#"Images"];
[image setObject:self.releaseDate forKey:#"releaseDate"];
[image setObject:file forKey:#"file"];
[image setObject:fileType forKey:#"fileType"];
[image setObject:title forKey:#"titleLabel"];
[image setObject:deadline forKey:#"deadline"];
[image setObject:self.recipients forKey:#"recipientIds"];
[image setObject:[[PFUser currentUser] objectId] forKey:#"senderId"];
[image setObject:[[PFUser currentUser] username] forKey:#"senderName"];
[image saveInBackground];
PFObject *object = [self.objectsArray valueForKey:#"titleLabel"];
if(object != [self.objectsArray valueForKey:#"titleLabel"]){
self.titlesArray = [self.titlesArray arrayByAddingObject:object];
}
you are checking if the object is equal to what you just assigned. Also, you should be using a NSMutableArray but if you dont care, i dont care too. :) Saying that, i guess your else loop should look like this
self.objectsArray = objects;
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for(id obj in self.objectsArray){
PFObject *key = [self.objectsArray valueForKey:#"titleLabel"];
if(![dict objectForKey:key]){
[dict setValue:obj forKey:key];
}
}
for (id key in dict) {
NSLog(#"key: %#, value: %# \n", key, [dict objectForKey:key]);
}