第四章 Runtime应用:实现NSCoding的自动归档和自动解档

runtime提供的函数遍历Model自身所有属性,并对属性进行encodedecode操作。
通常系统自带的数据类型,如:字典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

猜你喜欢

转载自blog.csdn.net/potato512/article/details/80947946