1. using NSUserDefaults.
2. using NSKeyedArchiver.
Both are very standard methods provided by Cocoa, but as NSUserDefaults is designed for storing default settings rather than data inside the app, in most of the cases, you want to use NSKeyedArchiver instead.
To use NSKeyedArchiver, first of all you need to add a protocol called NSCoding to the class whose properties are supposed to be saved and then loaded in the app.
For example, you have a class called Student which is used to store some information about a student. Its header may look like this:
@interface Student : NSObject <NSCoding> {
NSString *studentID;
NSString *studentName;
}
@property (copy) NSString *studentID;
@property (copy) NSString *studentName;
+ (Student *)initWithStudentID:(NSString *)ID andStudentName:(NSString *)name;
@end
+ (Student *)initWithStudentID:(NSString *)ID andStudentName:(NSString *)name {
Student *student = [[Student alloc] init];
student.studentID = [NSString stringWithString:ID];
student.studentName = [NSString stringWithString:name];
return [student autorelease];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
[self setStudentID:[aDecoder decodeObjectForKey:@"studentID]];
[self setStudentName:[aDecoder decodeObjectForKey:@"studentName"]];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:studentID forKey:@"studentID"];
[aCoder encodeObject:studentName forKey:@"studentName"];
}
Now we are on the halfway. What we need to do then is to tell the app that we want to save some data before it is terminated. Find the applicationWillTerminate: method in YourProjectAppDelegate.m file, and add the following code:
- (void)applicationWillTerminate:(NSNotification *)notification {
[self saveDataToDisk];
}
- (void)saveDataToDisk {
NSString *path = @"~/Documents/data";
path = [path stringByExpandingTildeInPath];
NSMutableDictionary *rootObject;
rootObject = [NSMutableDictionary dictionary];
[rootObject setValue:student forKey:@"student"];
[NSKeyedArchiver archiveRootObject:rootObject toFile:path];
}
The object student is an instance of Class Student. In this example, we save it in a file named data under the the Documents folder.
Alright, now we should be able to save our data into the disk. Now the only thing left is to load the data. The method may look like this:
- (void)loadDataFromDisk {
NSString *path = @"~/Documents/data";
path = [path stringByExpandingTildeInPath];
NSMutableDictionary *rootObject;
rootObject = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
if ([rootObject valueForKey:@"student"]) {
student = [rootObject valueForKey:@"student"];
}
}
You can call this method whenever you believe is necessary to load the data from local disk to your app.
Happy Coding :)
Instead of saving to a file, we can save it to user defaults... Thanks for the tutorial, btw.
ReplyDeleteThat's right. Thanks for your comment. :)
DeleteWorks for me, thanks for solution.
ReplyDeleteMy pleasure. ;)
DeleteBut what if i want to save a mutable array wich contains objects of type student? Do i just encode/decode the mutable array ?
ReplyDeleteI think NSKeyedArchiver/NSKeyedUnarchiver should work with arrays/dictionaries without any extra effort, as long as its elements support NSCoding
DeleteOk. Thank you very much :)
Delete