Objective-C:Runtime+自动化归档
Page content
Runtime+NSKeyedArchiver实现自动化归档解档
引言
在实际开发中,我们大部分项目会用到归档解档这一序列化存储数据的方式,对于需要归档的类,少则几个属性,多则十几个二十几个属性,有多少个属性,在归档和解档的代理中就需要添加多少行操作,属性变动后还需要逐行更改,冗长而繁琐。 应用Runtime,我们可以优雅的解决这个问题,使归档解档的init和encode操作自动化。
实例
我们创建要归档的用户类:User interface:
~~~objective-c
#import <Foundation/Foundation.h>
@interface User : NSObject
<NSCoding>
@property (nonatomic, strong) NSString * userId;
@property (nonatomic, strong) NSString * userName;
@property (nonatomic, strong) NSString * userAge;
@property (nonatomic, assign) NSString * userSex;
@property (nonatomic, strong) NSString * userPhone;
@property (nonatomic, strong) NSString * userAddress;
@end
~~~
implement:
~~~objective-c
#import "User.h"
#import <objc/runtime.h>
@implementation User
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
unsigned int count = 0;
objc_property_t * property_list = class_copyPropertyList([self class], &count);
for (unsigned int idx = 0; idx < count; idx ++) {
objc_property_t property = property_list[idx];
const char * property_name = property_getName(property);
NSString * name_str = [NSString stringWithUTF8String:property_name];
NSString * value = [aDecoder decodeObjectForKey:name_str];
[self setValue:value forKey:name_str];
}
free(property_list);
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
unsigned int count = 0;
objc_property_t * property_list = class_copyPropertyList([self class], &count);
for (unsigned int idx = 0; idx < count; idx ++) {
objc_property_t property = property_list[idx];
const char * property_name = property_getName(property);
NSString * name_str = [NSString stringWithUTF8String:property_name];
id value = [self valueForKey:name_str];
[aCoder encodeObject:value forKey:name_str];
}
free(property_list);
}
@end
~~~
就是这么简单,不需要针对特定属性逐一添加,Runtime自动获取属性列表并逐一对属性进行归档解档,实现自动化,我们来测试一下:
~~~objective-c
/**
* 归档User
*/
- (IBAction)keyedArchiver:(id)sender {
User * user = UNGetSerializedObject(KEY_USER);
if (!user) {
user = [User new];
}
user.userId = @"1001";
user.userName = @"赵钱孙李";
user.userAge = @"24";
user.userSex = @"1";
user.userPhone = @"18929291100";
user.userAddress = @"广东省广州市天河区";
UNSaveSerializedObject(user, KEY_USER);
}
/**
* 解档User
*/
- (IBAction)keyedUnArchiver:(id)sender {
User * user = UNGetSerializedObject(KEY_USER);
if (user) {
NSLog(@"user : %@\n, %@\n, %@\n, %@\n, %@\n, %@", user.userId, user.userName, user.userAge, user.userPhone, user.userAddress, user.userSex);
}
}
~~~
将自动化归结当操作放入基类,或者通过动态方法交换,以Aop的形式写入模型类,那么我们创建的数据模型类就不用进行重复的编解码实现了。