1

I'm trying to save an array of locations to NSUserDefaults. First I've converted the CLLocationCoordinates into an array of NSValues to be saved using NSUserDefaults. Here is my code so far:

_locationsArray = [[NSMutableArray alloc] init];
NSUInteger count = [self.locations count];
CLLocationCoordinate2D coordinates[count];
for (NSInteger i = 0; i < count; i++) {
    coordinates[i] = [(CLLocation *)self.locations[i] coordinate];
    NSValue *locationValue = [NSValue valueWithMKCoordinate:coordinates[i]];
    [_locationsArray addObject:locationValue];
}
NSLog(@"location = %@", _locationsArray);
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

[defaults setObject:totalDistance forKey:@"totalDistance"];
[defaults setObject:_locationsArray forKey:@"mapOverlay"];
// [defaults setDouble:_totalTime forKey:@"totalTime"];
[defaults setObject:avgSpeedToBeSaved forKey:@"averageSpeed"];
[defaults setObject:totalCalories forKey:@"totalCalories"];
[defaults synchronize];

However I get the following error:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSUserDefaults setObject:forKey:]: attempt to insert non-property list object (
    "<8b4df1d9 36ab4240 d5059bbe 47825ec0>",
    "<f6dd639f 36ab4240 a2a7b7f5 49825ec0>",
    "<f6dd639f 36ab4240 a2a7b7f5 49825ec0>",
    "<20c46379 36ab4240 5ff02732 4c825ec0>",
    "<20c46379 36ab4240 5ff02732 4c825ec0>",
    "<d24c9c81 36ab4240 2bd75f9f 4e825ec0>",
    "<d24c9c81 36ab4240 2bd75f9f 4e825ec0>",
    "<d810b96c 36ab4240 f4d96401 51825ec0>",
    "<d810b96c 36ab4240 f4d96401 51825ec0>"
) for key mapOverlay'

I thought that if I converted the coordinates to NSValues they would be fine to be saved to NSUserDefaults - Is that not the case? How else should I be doing this?

Guillaume Algis
  • 10,705
  • 6
  • 44
  • 72
Khledon
  • 193
  • 5
  • 23
  • 4
    Read the docs for `NSUserDefaults`. `NSValue` is not one of the supported data types. – rmaddy Mar 01 '14 at 15:31
  • related: [Why NSUserDefaults failed to save NSMutableDictionary in iPhone SDK?](http://stackoverflow.com/questions/471830/why-nsuserdefaults-failed-to-save-nsmutabledictionary-in-iphone-sdk/471920#471920) – Matthias Bauch Mar 01 '14 at 15:49
  • Just want to mention a possibly simpler alternative: Instead of NSValues, try defining a custom class X that holds the coordinates as NSNumber properties. Then add instances of X to the array. Another option is an array of dictionaries containing the coordinates as NSNumbers. –  Mar 01 '14 at 15:52

5 Answers5

0

like the error said: attempt to insert non-property list object

enter image description here

you need to implementation NSCoding protocol,if you dont know how to do ,check http://sam.roon.io/archiving-objective-c-objects-with-nscoding

hope will help you

Lee xw
  • 133
  • 9
  • The code you posted doesn't relate to the OP's code at all. You should clarify how to make use of `NSCoding` within the scope of the OP's question. – rmaddy Mar 01 '14 at 15:47
0

Why are you saving NSMutableArray to NSUserDefaults. It's not the correct way to save data.

You should save your data in plist file.

    [_locationsArray writeToFile:path atomically:YES];

Get All the location from the plist file

  _locationsArray=[NSMutableArray arrayWithContentsOfFile:path];

You can also use Database.

Sunny Shah
  • 12,990
  • 9
  • 50
  • 86
  • I think this could be my option here but when I try and retrieve the data from the plist file my locations array is blank here is the code I'm using: `NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ActivityCompleted.plist"]; _locationsArray = [NSMutableArray arrayWithContentsOfFile:path];` and `NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ActivityCompleted.plist"]; _locationsArray = [NSMutableArray arrayWithContentsOfFile:path];` to retrieve – Khledon Mar 01 '14 at 17:52
0

Well one thing you can do archieve your array using NSKeyedArchiever and set into the userdefaults. And when you want to read the same unarchieve your array using NSKeyedUnarchiever.

Hussain Shabbir
  • 14,801
  • 5
  • 40
  • 56
0

Try saving values instead of objects.

[defaults setValue:(id) forKey:(NSString *)];

It works, as (id) can be basically be "anything" and it doesn't crash. :)

emotality
  • 12,795
  • 4
  • 39
  • 60
0

well its asking for a "property list object" which is NSDictionary/XML/Plist. Try saving it into a Dictionary?

for (NSInteger i = 0; i < count; i++) {
    coordinates[i] = [(CLLocation *)self.locations[i] coordinate];
    NSValue *locationValue = [NSValue valueWithMKCoordinate:coordinates[i]];
    [_locationsArray addObject:locationValue];
}
NSMutableDictionary *locationsDict = @{@"locationsArray": _locationsArray};

[defaults setObject:locationsDict forKey:@"mapOverlay"];
[defaults synchronize];

Let us know if this works :)

emotality
  • 12,795
  • 4
  • 39
  • 60
  • Thanks for the advice. Just a quick question: the reason I want to save the locations array is I can use it to build an MKPolyline in the next view, how would I rebuild the array from a NSDictionary? – Khledon Mar 01 '14 at 17:43
  • NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSMutableArray *mapOverlay = [[defaults objectForKey:@"mapOverlay"] valueForKey:@"locationsArray"]; – emotality Mar 01 '14 at 17:49