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