NSMutableDictionary in to NSUserDefaults "Attempt to set a non-property-list object" - nsuserdefaults

I'm trying save NSMutableDictionary in to NSUserDefaults. My code:
NSDictionary *command = [_otherVC.arrayCommandsAddComandVC objectAtIndex:indexPath.row];
NSString *commandID = [command objectForKey:#"id"];
[_otherVC.selectedCommands addObject:command];
NSMutableDictionary *commandPush = [[NSMutableDictionary alloc]initWithObjectsAndKeys:[NSNumber numberWithBool:1], #"news",
[NSNumber numberWithBool:1], #"articles",
[NSNumber numberWithBool:1], #"foto",
[NSNumber numberWithBool:1], #"video",
[NSNumber numberWithBool:1], #"matchStart",
[NSNumber numberWithBool:1], #"scoreChange",
[NSNumber numberWithBool:1], #"matchFinished", nil];
[_otherVC.settingsToPush setObject:commandPush forKey:commandID];
In other method i write to NSUserDefaults with helpers:
defaults_set_object_wo(#"settings/push/settings_to_push", _otherVC.settingsToPush);
And i have error:
Attempt to set a non-property-list object {
1 = {
articles = 1;
foto = 1;
matchFinished = 1;
matchStart = 1;
news = 1;
scoreChange = 1;
video = 1;
};
} as an NSUserDefaults value for key settings/push/settings_to_push

Related

Downloading Remote PLIST iOS - Returning Null

Struggling with this one. Looking to download a read only plist for use inside my app...
However struggling to read the contents in a Dictionary... Code below, any pointers would be great..
-(void)loadProducts {
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:#"https://dl.dropboxusercontent.com/s/f1nmq1wa7gs96dp/Region1Products.plist"]];
for (NSDictionary* productDictionary in dict) {
ProductItem* productItem = [[ProductItem alloc] init];
productItem.picturesCount = [productDictionary objectForKey:#"PicturesCount"];
productItem.maxPicturesCount = [productDictionary objectForKey:#"MaxPicturesCount"];
productItem.size = [productDictionary objectForKey:#"Size"];
productItem.previewImageName = [productDictionary objectForKey:#"ImageName"];
productItem.sequence = [productDictionary objectForKey:#"Sequence"];
productItem.productName = [productDictionary objectForKey:#"Name"];
productItem.type = [productDictionary objectForKey:#"ProductType"];
productItem.prices = [productDictionary objectForKey:#"Prices"];
productItem.shippingPrices = [productDictionary objectForKey:#"ShippingPrices"];
productItem.description = [productDictionary objectForKey:#"Description"];
productItem.popupMessage = [productDictionary objectForKey:#"PopupMessage"];
productItem.popupDetailMessage = [productDictionary objectForKey:#"PopupDetailMessage"];
productItem.incrementalPricing = [[productDictionary objectForKey:#"IncrementalPricing"] boolValue];
if (YES == productItem.incrementalPricing) {
productItem.incrementalPrices = [productDictionary objectForKey:#"IncrementalPrices"];
}
NSArray *previewItems = [productDictionary objectForKey:#"PreviewItems"];
for (NSDictionary* previewItem in previewItems) {
[productItem addProductPreviewItemFromDictionary:previewItem];
}
[self.productsList addObject:productItem];
}
You're creating an NSDictionary from the url, but the top level object in that plist is an array. To solve this, you can change dict to an NSArray object. I used the following simplified code to test this:
NSArray *array = [NSArray arrayWithContentsOfURL:[NSURL URLWithString:#"https://dl.dropboxusercontent.com/s/f1nmq1wa7gs96dp/Region1Products.plist"]];
for (NSDictionary* productDictionary in array) {
NSLog(#"%#",productDictionary);
}

Sorting mutable array by dictionary key

I have already looked through a few answers using the various sorting methods of NSMutableArray, but for some reason they are not working for me.
I am just trying to sort the mutable array which contains dictionaries by the Delay key within each dictionary. However, the "sorted" array is the exact same as the original array.
By the way, it works fine if I create a dummy mutable array and populate it with dictionaries containing numbers, but for some reason it won't sort this mutable array that I am initializing.
What am I doing wrong?
Here's my code:
playlistCalls = [[NSMutableArray alloc] initWithArray:[currentPlaylist objectForKey:#"Tunes"]];
NSLog(#"original %#", playlistCalls);
NSSortDescriptor *delay = [NSSortDescriptor sortDescriptorWithKey:#"Delay" ascending:YES];
[playlistCalls sortUsingDescriptors:[NSArray arrayWithObject:delay]];
NSLog(#"sorted %#", playlistCalls);
Here's the array containing the dictionaries:
2012-06-04 15:48:09.129 MyApp[57043:f503] original (
{
Name = Test Tune;
Delay = 120;
Volume = 100;
},
{
Name = Testes;
Delay = 180;
Volume = 100;
},
{
Name = Testing;
Delay = 60;
Volume = 100;
}
)
2012-06-04 15:48:09.129 MyApp[57043:f503] sorted (
{
Name = Test Tune;
Delay = 120;
Volume = 100;
},
{
Name = Testes;
Delay = 180;
Volume = 100;
},
{
Name = Testing;
Delay = 60;
Volume = 100;
}
)
The code above is fine when I use NSNumbers in my dictionary. That leads me to believe that the Delay value is stored as strings in your dictionary. What you will need to do then is sort by the strings integerValue.
NSSortDescriptor *delay =
[NSSortDescriptor sortDescriptorWithKey:#"Delay.integerValue" ascending:YES];
Please try the following, it worked with me
NSDictionary *dic;
NSMutableArray *arr = [[NSMutableArray alloc] init];
dic = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:120], #"Delay",
[NSNumber numberWithInt:100], #"Volume",
nil];
[arr addObject:dic];
dic = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:160], #"Delay",
[NSNumber numberWithInt:100], #"Volume",
nil];
[arr addObject:dic];
dic = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:100], #"Delay",
[NSNumber numberWithInt:100], #"Volume",
nil];
[arr addObject:dic];
NSSortDescriptor *sortDesc = [[NSSortDescriptor alloc] initWithKey:#"Delay" ascending:YES];
[arr sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];

Geting value from NSMutableArray after using sortedArrayUsingDescriptors

I have made a NSDictionary HospitalDictionary which holds latitude,longitude and distances
NSMutableArray *HospitalArray = [NSMutableArray array];
NSDictionary *HospitalDictionary = [[NSDictionary alloc]init];
NSString *LATITUDE = #"latitude";
NSString *LONGITUDE = #"longitude";
NSString *DISTANCE = #"distance";
for (int i=0; i<=100; i++) {
// calculations for coordinates and distance are done ....
HospitalDictionary = [NSDictionary dictionaryWithObjectsAndKeys:latitude, LATITUDE,
longitude, LONGITUDE,[NSNumber numberWithInt:distanceInKm], DISTANCE, nil];
[HospitalArray addObject:HospitalDictionary];
{
Then data is short using following code
// These line are added to short the Dictionary added to Array List with the Key of Distance
NSSortDescriptor *distanceDescriptor = [[NSSortDescriptor alloc] initWithKey:DISTANCE ascending:YES];
id obj;
NSEnumerator * enumerator = [HospitalArray objectEnumerator];
NSArray *descriptors = [NSArray arrayWithObjects:distanceDescriptor, nil];
NSArray *sortedArray = [HospitalArray sortedArrayUsingDescriptors:descriptors];
enumerator = [sortedArray objectEnumerator];
// this will print out the shorted list for DISTANCE
while ((obj = [enumerator nextObject])) NSLog(#"%#", obj);
// this will return the object at index 1
NSLog(#"Selected array is %#",[sortedArray objectAtIndex:1]);
Output of this is -
2012-05-30 08:24:42.784 Hospitals[422:15803]
sorted array is
{
distance = 1;
latitude = "27.736221";
longitude = "85.330095";
}
I want to get only Latitude or Longitude for the ObjectAtIndex:1 for the sortedArray. How can i get the particular value ie. latitude out of sortedArray not the complete list.
To access a property/method of an object in an array, you can use something like this:
NSLog(#"Latitude for object at index 1 is %#",[[sortedArray objectAtIndex:1] latitude]);

Highest 4 Numbers From Array #1 To Store In Another Array

So I have three different arrays involved here...
I'm looping through golferThreeIcons (NSMutableArray), and I'm trying to take the highest 4 results (golferThreeIcons contains #'s as strings) and store them into the topFourIconsNum (NSMutableArray) and then I plan to store the id of that highest number in the array topFourIconsId (NSMutableArray).
One tricky thing is that golferThreeIcons start out at 99, but I want that to act like zero. So the number 99 should not get added to either of the arrays...
Example:
golferThreeIcons {2,1,5,3,9}
And after the loop went through I want it to show something like this...
topFourIconsId {0,2,3,4} --- 0 corresponds to 2 in golferThreeIcons --- 2 corresponds to 5 in golfer three icons
topFourIconsNum {2,5,3,9} ----(in any order as long as it corresponds to the top four icons id)
NSMutableArray *topFourIconsId = [NSMutableArray arrayWithObjects: #"0", #"0", #"0", #"0", #"0" ,nil];
NSMutableArray *topFourIconsNum = [NSMutableArray arrayWithObjects: #"0", #"0", #"0", #"0", #"0" ,nil];
int *ids = 0;
for (NSString *s in golferThreeIconCounter) {
if(s != #"0") {
int sint = [s intValue];
int *idn = 0;
for(NSString *n in topFourIconsNum) {
int nint= [n intValue];
if(sint == 99 && nint == 0) {
NSString *idstring = [NSString stringWithFormat:#"%d", ids];
NSString *sintstring = [NSString stringWithFormat:#"%d", sint];
[topFourIconsId replaceObjectAtIndex:idn withObject:idstring];
[topFourIconsNum replaceObjectAtIndex:idn withObject:sintstring];
NSLog(#"IN %#",sintstring);
break;
}
else {
if (sint > nint) {
NSString *idstring = [NSString stringWithFormat:#"%d", ids];
NSString *sintstring = [NSString stringWithFormat:#"%d", sint];
[topFourIconsId replaceObjectAtIndex:idn withObject:idstring];
[topFourIconsNum replaceObjectAtIndex:idn withObject:sintstring];
NSLog(#"IN %#",sintstring);
break;
}
}
idn++;
}
}
ids++;
}
Just a crazy idea
Put your golferThreeIcons in a NSDictionary with the array index as the key and the array value as the value and then sort the keys on their value:
NSDictionary *dict = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"2", #"1", #"5", #"3", #"9", nil] forKeys:[NSArray arrayWithObjects:#"0", #"1", #"2", #"3", #"4", nil]];
NSArray *sortedKeys = [dict keysSortedByValueUsingSelector:#selector(caseInsensitiveCompare:)];
NSLog([sortedKeys description]);

NSMutableArray of Objects

First off I am very new to Objective C and iPhone programming. Now that that is out of the way. I have read through most of the Apple documentation on this and some third party manuals.
I guess I just want to know if I'm going about this the correct way ...
- (NSMutableArray *)makeModel {
NSString *api = #"http://www.mycoolnewssite.com/api/v1";
NSArray *namesArray = [NSArray arrayWithObjects:#"News", #"Sports", #"Entertainment", #"Business", #"Features", nil];
NSArray *urlsArray = [NSArray arrayWithObjects:
[NSString stringWithFormat:#"%#/news/news/25/stories.json", api],
[NSString stringWithFormat:#"%#/news/sports/25/stories.json", api],
[NSString stringWithFormat:#"%#/news/entertainment/25/stories.json", api],
[NSString stringWithFormat:#"%#/news/business/25/stories.json", api],
[NSString stringWithFormat:#"%#/news/features/25/stories.json", api], nil];
NSMutableArray *result = [NSMutableArray array];
for (int i = 0; i < [namesArray count]; i++) {
NSMutableDictionary *objectDict = [NSMutableDictionary dictionary];
NSString *name = (NSString *)[namesArray objectAtIndex:i];
NSString *url = (NSString *)[urlsArray objectAtIndex:i];
[objectDict setObject:name forKey:#"NAME"];
[objectDict setObject:url forKey:#"URL"];
[objectDict setObject:#"NO" forKey:#"HASSTORIES"];
[result addObject:objectDict];
}
return result;
}
The output of the result is ...
(
{
HASSTORIES = NO;
NAME = News;
URL = "http://www.mycoolnewssite.com/api/v1/news/news/25/stories.json";
},
{
HASSTORIES = NO;
NAME = Sports;
URL = "http://www.mycoolnewssite.com/api/v1/news/sports/25/stories.json";
},
{
HASSTORIES = NO;
NAME = Entertainment;
URL = "http://www.mycoolnewssite.com/api/v1/news/entertainment/25/stories.json";
},
{
HASSTORIES = NO;
NAME = Business;
URL = "http://www.mycoolnewssite.com/api/v1/news/business/25/stories.json";
},
{
HASSTORIES = NO;
NAME = Features;
URL = "http://www.mycoolnewssite.com/api/v1/news/features/25/stories.json";
}
)
Any insight would be appreciated ;-)
It looks fine. There can be some minor improvements if you care.
1.
[NSString stringWithFormat:#"%#/news/news/25/stories.json", api]
can be replaced by
[api stringByAppendingString:#"/news/news/25/stories.json"]
if there's no chance the api appears in the middle or accepts other arguments.
2.
NSString *name = (NSString *)[namesArray objectAtIndex:i];
NSString *url = (NSString *)[urlsArray objectAtIndex:i];
The explicit cast is unnecessary. An id can be implicitly casted to and from other ObjC objects.
3.
You could use a convenient method -dictionaryWithObjectsAndKeys: to construct the dictionary in one-shot, so you don't need a temperary dictionary:
[result addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:
name, #"NAME",
url, #"URL",
#"NO", #"HASSTORIES", nil]];
4. (optional)
This transform is not useful if the function is not a hot spot.
Since the arrays are only used locally, it's more efficient to use a C array.
static const int arraySize = 5;
NSString* namesCArray[] = {#"News", #"Sports", #"Entertainment", #"Business", #"Features"};
NSString* urlsCArray[arraySize];
urlsArray[0] = [api stringByAppendingString:#"/news/news/25/stories.json"];
...
for (int i = 0; i < arraySize; ++ i) {
...
NSString* name = namesCArray[i];
NSString* url = urlsCArray[i];
...
}
this removes the repeated -count and -objectAtIndex: calls which is very slow compared with direct element access.
5. (optional)
This transform is not useful if the array is short.
You could use fast-enumeration to loop over an ObjC container:
int i = 0;
for (NSString* name in namesArray) {
NSString* url = [urlsArray objectAtIndex:i];
...
++ i;
}
6.
Usually we use [NSNumber numberWithBool:NO] to represent a boxed true/false value, instead of a string #"NO". NSNumber is also used a lot whenever a primitive number (int, float, etc.) cannot be used (e.g. to be stored in an NSArray). I don't know if your API explicitly requires a string NO, so it may not unsuitable for you.