1
votes

First of all: Merry Christmas everyone! It has been some time since I was able to store data into NSUserDefaults.

In this case I want to store a NSMutableArray to the NSUserDefaults. It is clear to me that you can only store immutable objects to this "file".

I had tried the following code for loading the NSMutableArray:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
self.mutableArray = [[NSMutableArray alloc] initWithArray: [defaults objectForKey:@"TestKey"]];

I am using the following code for storing the data:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *tempArr = [NSArray arrayWithArray:self.mutableArray];
[defaults setObject:tempArr forKey:@"TestKey"];
[defaults synchronize];

Unfortunately, the simulator exits with the following error:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSUserDefaults setObject:forKey:]: attempt to insert non-property list object (
"<MyObject: 0x10dfb40a0>"
) for key TestKey'

The mutable array contains NSObjects.

Does anyone have a clue where I am screwing up?

4
What is in self.mutableArray? - zaph
The self.mutableArray contains NSObjects consisting of NSString elements - Alex van Rijs
nslog the value of tempArr and check taht does it contains data - kamalesh kumar yadav
NSLog prints: Temparr is: ( "<MyObject: 0x10b86c600>" ) - Alex van Rijs
NSUserDefaults can not contain NSObjects, see the documentation: A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. You will have to convert your NSObject to one of these. - zaph

4 Answers

3
votes

You can try this:

To Archive:

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:YOUR_MUTABLE_ARRAY];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"myarray"];
[[NSUserDefaults standardUserDefaults] synchronize];

To Unarchive:

NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"myarray"];
NSMutableArray *mArr = [NSKeyedUnarchiver unarchiveObjectWithData:data];
2
votes

You cannot save tempArr to the NSUserDefaults because as you show in comment this array contains subclasses of MyObject which is custom object. If you want to save it to NSUserDefaults you should implement NSCoding protocol and add two method:

- (void)encodeWithCoder:(NSCoder *)encoder {
    //Encode all yours properties, vars
    [encoder encodeObject:self.property1 forKey:@"property1"];
    [encoder encodeObject:self.property2 forKey:@"property2"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    if((self = [super init])) {
        //decode all yours properties, vars
        self.property1 = [decoder decodeObjectForKey:@"property1"];
        self.property2 = [decoder decodeObjectForKey:@"property2"];
    }
    return self;

But NSUserDefaults was design to store just simple data and if you want to save more custom objects you should consider save it to the file, have a look on NSKeyedArchiver maybe that will be more suitable for you. Just remember that if you want to save custom object with NSKeyedArchiver the object should conform to NSCoding protocol as well and you have to add this two method above too.

1
votes

NSUserDefaults can not handle custom objects.

From the Apple docs:

A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any other type of object, you should typically archive it to create an instance of NSData.

For custom objects either convert then to one of these objects or implement the NSCoder protocol for the class to create an NSData representation.

For more than a small number of parameters the best choice is either CoreData or NSKeyedArchiver saving to a file in the Documents directory.

0
votes

Your two options are:

  1. Implement NSCoding in MyObject and then use a NSKeyedArchiver

  2. Use CoreData

A very good tutorial and a comparison of both can be found here: http://nshipster.com/nscoding/