Looyao's Blog

记录一些点滴

Objective-c 对象的持久化

| Comments

有些时候我们想把自定义类的对象保存起来, 保存到指定文件或者简单点直接使用NSUserDefault来保存, 这个过程应该可以叫做对象的持久化.

要想持久化对象, 首先需要在自定义类实现NSCoding这个协议, 引用下文档内容:

The NSCoding protocol declares the two methods that a class must implement so that instances of that class can be encoded and decoded.

encode的意思就是把类实例(对象)转化为字节流, 这个过程可以叫做序列化吧, 这样我们就可以把字节流保存起来了.

假设我们有一个info类, 用来保存信息.

1
2
3
4
5
6
7
8
@interface Info : NSObject <NSCoding>
{
    NSString *name;
    NSInteger age;
}
@property (nonatomic, retain) NSString *name;
@property (nonatomic, assign) NSInteger age;
@end

下边来看看具体实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#import "Info.h"

@implementation Info
@synthesize name;
@synthesize age;

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    if (self) {
        name = [[aDecoder decodeObjectForKey:@"name"] retain];
        age = [aDecoder decodeIntegerForKey:@"age"];
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:name forKey:@"name"];
    [aCoder encodeInteger:age forKey:@"age"];
}

- (void)dealloc
{
    [name release];
    [super dealloc];
}

@end

我们实现了NSCoding的两个方法, 一个编码, 一个解码. 实现了之后我们就可以把对象序列化为字节流了, 使用NSKeyedArchiver.

1
2
3
4
5
6
7
8
Info *infoObj = [[Info alloc] init];
infoObj.name = @"apple";
infoObj.age = 9;

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:infoObj]; //把对象infoObj变为字节流了, 可以保存到文件中或者使用USUserDefault来保存.
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
[userDefault setObject:data forKey:@"InfoTest"];
[userDefault synchronize];

保存之后, 需要把字节流还原为对象

1
2
3
4
5
6
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
NSData *data = [userDefault objectForKey:@"InfoTest"];
if (data) {
    Info *infoObj = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    NSLog(@"name: %@, age: %d", infoObj.name, infoObj.age);
}

这样类的持久化就完成了, 当然也可以把自定义类对象放到NSArray等一些内建数据结构中, 同样可以持久化, 只要自定义类中实现了NSCoding协议方法即可.

Comments