Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to save to nsuserdefaults for custom class?

If I have a custom class Person which has three variables (which are propertized and synthesized):

NSString* theName;
float* theHeight;
int theAge;

Person instances are stored in an NSArray 'Group'. There is only one Group. What is the best way of storing and loading the Group in NSUserDefaults? (bearing in mind that float and int are not legal for NSUserDefaults)

like image 932
cannyboy Avatar asked Jun 08 '10 18:06

cannyboy


2 Answers

@Brad Smith's answer is not complete, and even is incorrect in some sense. We have to use NSKeyedArchiver and NSKeyedUnarchiver as follows:

Make your class (for example in this case Person) to conform to protocol NSCoding and implement both the methods as:

- (id)initWithCoder:(NSCoder *)decoder {
    self = [super init];
    if(self) {
        self.name = [decoder decodeObjectForKey:<key_for_property_name>];
        // as height is a pointer
        *self.height = [decoder decodeFloatForKey:<key_for_property_height>];
        self.age = [decoder decodeIntForKey:<key_for_property_age>];
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:self.name forKey:<key_for_property_name>];
    //as height is a pointer
    [encoder encodeFloat:*self.height forKey:<key_for_property_height>]
    [encoder encodeInt:self.age forKey:<key_for_property_age>];
}

Using NSUserDefaults

// Write to NSUserDefaults
NSData *archivedObject = [NSKeyedArchiver archivedDataWithRootObject:<your_class_object>];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:archivedObject forKey:<key_for_archived_object>];
[defaults synchronize];

// Read from NSUserDefaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *archivedObject = [defaults objectForKey:<key_for_archived_object>];
<your_class> *obj = (<your_class> *)[NSKeyedUnarchiver unarchiveObjectWithData:archivedObject];
like image 85
Vasu Avatar answered Nov 08 '22 10:11

Vasu


I find implementing encodeWithCoder and initWithCoder quite boring, especially if you have many attributes in your class, and many classes to save to NSUserDefaults.

I create a library RMMapper (https://github.com/roomorama/RMMapper) to help save custom object into NSUserDefaults easier and more convenient.

To mark a class as archivable, just use: #import "NSObject+RMArchivable.h"

To save a custom object into NSUserDefaults:

#import "NSUserDefaults+RMSaveCustomObject.h"

NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults rm_setCustomObject:user forKey:@"SAVED_DATA"];

To get custom obj from NSUserDefaults:

user = [defaults rm_customObjectForKey:@"SAVED_DATA"]; 
like image 40
thomasdao Avatar answered Nov 08 '22 12:11

thomasdao