(一一五)利用NSKeyedArchiver实现任意对象转为二进制

时间:2021-02-05 15:16:15

【应用背景】

在数据库中存储数据时,如果对象过于复杂,又不必要创建复杂的表,可以直接把整个对象转化为二进制存入数据库字段,然后取出后再还原即可。

【实现方法】

在PHP中,使用序列化和反序列化可以实现这样的功能。

在OC中,使用NSKeyedArchiver和NSKedUnarchiver可以实现对象转二进制和二进制转对象,要实现转化,必须遵循NSCoding协议,并且实现encodeWithCoder方法用来转化数据为二进制,实现initWithCoder实现二进制数据还原成类对象,OC的常见类,例如数组、字典等已经实现了这些内容,直接转换即可,如果是自己定义的类,需要手动实现。

下面以将自定义的Person类转化为二进制存储,然后再读取出来的过程,来加深对这个功能的理解。

【具体案例】

①定义Peron类,有三个属性,如下,注意要遵循NSCoding协议。

#import <Foundation/Foundation.h>

@interface Person : NSObject <NSCoding>

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, assign) double height; @end

②实现编码和解码的方法,并且重写description方法方便打印类内数据。

注意:encode和decode时要选择合适的数据类型。

#import "Person.h"

@implementation Person

- (void)encodeWithCoder:(NSCoder *)encoder{

    [encoder encodeObject:self.name forKey:@"name"];
[encoder encodeInteger:self.age forKey:@"age"];
[encoder encodeDouble:self.height forKey:@"height"]; } - (id)initWithCoder:(NSCoder *)decoder{ if (self = [super init]) { self.name = [decoder decodeObjectForKey:@"name"];
self.age = [decoder decodeIntegerForKey:@"age"];
self.height = [decoder decodeDoubleForKey:@"height"];
} return self; } - (NSString *)description{ return [NSString stringWithFormat:@"%@ %ld %lf",_name,_age,_height]; } @end

③随机生成一些Person对象,使用NSKeyedArchiver进行二进制转换,然后存入文件,注意到因为对象放到了数组里,因此对象不需要主动转化为二进制,这个过程会自动完成,注意一定要实现上面的decode和encode方法。

NSMutableArray *persons = [NSMutableArray array];
for (int i = 0; i < 100; i++) {
Person *p = [[Person alloc] init];
p.name = [NSString stringWithFormat:@"<%05d>",arc4random_uniform(10000)];
p.age = arc4random_uniform(100);
p.height = 1.5 + arc4random_uniform(60) / 100.0;
[persons addObject:p];
}
[NSKeyedArchiver archiveRootObject:persons toFile:@"/Users/soulghost/Desktop/persons.data"];

④读取文件,使用NSKeydUnarchiver进行还原,在还原数组时,数组内的数据也被自动还原。

NSMutableArray *persons = [NSKeyedUnarchiver unarchiveObjectWithFile:@"/Users/soulghost/Desktop/persons.data"];
NSLog(@"%@",persons);

由于重写了description方法,类的内容会规范的打印如下:

    "<07060> 10 1.960000",
"<05393> 35 1.960000",
"<01438> 68 1.920000",
"<00835> 40 1.710000",
"<00035> 14 1.780000",
"<08394> 66 1.910000",
"<00504> 29 1.580000",
"<03072> 4 1.900000",
"<00473> 7 1.800000",
"<04528> 10 1.790000",
"<05930> 3 1.790000",
"<07390> 2 1.590000",
"<00820> 62 1.670000",
...

通过这么一个简单的案例,就能学会任意对象和二进制对转的方法,这个方法能够跨越不同语言间的类定义不同而实现统一的数据存储,能够轻松实现类的数据库存储。