用runtime
提供的函数遍历Model自身所有属性,并对属性进行encode
和decode
操作。
通常系统自带的数据类型,如:字典NSDictionary,数组NSArray,字符串NSString,布尔数据BOOL,数字对象NSNumber,NSData,NSDate等可以直接进行存储操作;但是自定义的数据类型,如果直接进行存储操作时,则会抛出异常,这时候就需要进行归档、解档处理。
示例代码
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSNumber *age;
@property (nonatomic, strong) NSString *address;
@property (nonatomic, strong) NSString *company;
@property (nonatomic, strong) NSString *job;
@end
#import "Person.h"
#import <objc/runtime.h>
@implementation Person
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init])
{
unsigned int outCount;
Ivar *ivars = class_copyIvarList([self class], &outCount);
for (int i = 0; i < outCount; i ++)
{
Ivar ivar = ivars[i];
NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
[self setValue:[aDecoder decodeObjectForKey:key] forKey:key];
}
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
unsigned int outCount;
Ivar *ivars = class_copyIvarList([self class], &outCount);
for (int i = 0; i < outCount; i ++)
{
Ivar ivar = ivars[i];
NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
[aCoder encodeObject:[self valueForKey:key] forKey:key];
}
}
@end
使用
// 自动归档/解档
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"PersonInfo"];
if (data) {
// 解档使用
Person *person = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSLog(@"name: %@", person.name);
} else {
Person *person = [Person new];
person.name = @"devZhang";
person.age = @(35);
person.company = @"ShengXue";
person.job = @"iOSDev";
person.address = @"龙岗坂田国际中心";
// 归档存储
data = [NSKeyedArchiver archivedDataWithRootObject:person];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"PersonInfo"];
}
未进行归档、解档时报错
// 归档错误
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person encodeWithCoder:]: unrecognized selector sent to instance 0x600000450d40'
// 解档错误
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person initWithCoder:]: unrecognized selector sent to instance 0x60000005d760'
使用自动归档、解档后,自定义类型数据处理正常
2018-07-07 00:26:20.023737+0800 DemoRuntime[1850:81640] name: devZhang