在 iOS 中归档数据时,如果归档的是我们自定义的数据模型类,则需要我们手动进行序列化和反序列化才能进行归档.
在此,我们使用 runtime 进行序列化和反序列化,思路大致为:新建一个数据模型的基类,基类.h
文件中不需要写任何属性, 然后在基类的.m
文件中利用 runtime 进行序列化和反序列化,至此基类已经完成.此后如果我们工程中哪一个数据模型类需要进行归档存储,就可以直接继承前面的基类即可.也就是说继承基类的其它数据模型类无需再进行序列化和反序列化就可以进行归档数据.
不多说,开始做,上代码,以下是步骤:
1.新建数据模型基类WLNSObject
基类一定要遵守NSCoding
协议.
.h
文件如下:
#import <Foundation/Foundation.h>
@interface WLNSObject : NSObject<NSCoding>
@end
.m
文件如下:
#import "WLNSObject.h"
#import <objc/runtime.h>
@implementation WLNSObject
//序列化
-(void)encodeWithCoder:(NSCoder *)aCoder{
unsigned int ivarCount = 0;
Ivar *ivars = class_copyIvarList([self class], &ivarCount);
for (unsigned int i = 0; i < ivarCount; i++) {
const char *ivar_name = ivar_getName(ivars[i]);
NSString *key = [NSString stringWithCString:ivar_name encoding:NSUTF8StringEncoding];
[aCoder encodeObject:[self valueForKey:key] forKey:key];
}
}
//反序列化
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super init];
if (self) {
unsigned int ivarCount = 0;
Ivar *ivars = class_copyIvarList([self class], &ivarCount);
for (unsigned int i = 0; i < ivarCount; i++) {
const char *ivar_name = ivar_getName(ivars[i]);
NSString *key = [NSString stringWithCString:ivar_name encoding:NSUTF8StringEncoding];
[self setValue:[coder decodeObjectForKey:key] forKey:key];
}
}
return self;
}
@end
2.新建继承基类WLNSObject
的数据模型Man
Man
的.h
文件如下:
#import "WLNSObject.h"
@interface Man : WLNSObject
@property (nonatomic, strong) NSString *name;
@end
Man
的.m
文件中不需要任何操作,在这里就不列出了.
3.新建继承基类WLNSObject
的数据模型Person
Person
的.h
文件如下:
#import <Foundation/Foundation.h>
#import "WLNSObject.h"
#import "Man.h"
@interface Person : WLNSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, strong) Man *friend;
@end
Person
的.m
文件中不需要任何操作,在这里就不列出了.
4.进行归档测试
在main.m
中进行测试, 如下:
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *obj = [[Person alloc] init];
obj.name = @"Jack";
obj.age = 27;
obj.friend = [[Man alloc] init];
obj.friend.name = @"Tom";
//归档
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:obj] forKey:@"myObj"];
[[NSUserDefaults standardUserDefaults] synchronize];
//反归档
Person *p = [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] dataForKey:@"myObj"]];
NSLog(@"p.name:%@, p.age:%lu, p.friend.name = %@", p.name, p.age, p.friend.name);
}
return 0;
}
输出结果如下图:
至此,我们所有继承基类WLNSObject
的数据模型无需再进行序列化和反序列化就可以进行归档数据了.