Best way to save to nsuserdefaults for custom class?

10,635

Solution 1

@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];

Solution 2

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"]; 
Share:
10,635
cannyboy
Author by

cannyboy

Updated on June 05, 2022

Comments

  • cannyboy
    cannyboy almost 2 years

    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)

  • Andrew-Dufresne
    Andrew-Dufresne over 11 years
    I wish I can upvote your answer to the top. Brad Smith is totally misleading.
  • gdubs
    gdubs about 10 years
    @Kailash , so what's the use of the encode and decode methods? What encoder should I pass when instantiating it? Or is that automatically called when saving and reading?
  • Vasu
    Vasu about 10 years
    @gdubs, yes those methods are called by os itself.