(一一五)利用NSKeyedArchiver实现任意对象转为二进制
【应用背景】
在数据库中存储数据时,如果对象过于复杂,又不必要创建复杂的表,可以直接把整个对象转化为二进制存入数据库字段,然后取出后再还原即可。
【实现方法】
在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", ...
通过这么一个简单的案例,就能学会任意对象和二进制对转的方法,这个方法能够跨越不同语言间的类定义不同而实现统一的数据存储,能够轻松实现类的数据库存储。