Runtime的入门与应用之七-归档与解档

来源:互联网 发布:服务行业大数据案例 编辑:程序博客网 时间:2024/06/05 20:47

如果你实现过自定义模型数据持久化的过程,那么你也肯定明白,如果一个模型有许多个属性,那么我们需要对每个属性都实现一遍encodeObject 和decodeObjectForKey方法,如果这样的模型又有很多个,这还真的是一个十分麻烦的事情。下面来看看简单的实现方式。

假设现在有一个Movie类,有3个属性,它的h文件这这样的

#import <Foundation/Foundation.h>//1. 如果想要当前类可以实现归档与反归档,需要遵守一个协议NSCoding@interface Movie : NSObject<NSCoding>@property (nonatomic, copy) NSString *movieId;@property (nonatomic, copy) NSString *movieName;@property (nonatomic, copy) NSString *pic_url;@end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

如果是正常写法, m文件应该是这样的:

#import "Movie.h"@implementation Movie- (void)encodeWithCoder:(NSCoder *)aCoder{    [aCoder encodeObject:_movieId forKey:@"id"];    [aCoder encodeObject:_movieName forKey:@"name"];    [aCoder encodeObject:_pic_url forKey:@"url"];}- (id)initWithCoder:(NSCoder *)aDecoder{    if (self = [super init]) {        self.movieId = [aDecoder decodeObjectForKey:@"id"];        self.movieName = [aDecoder decodeObjectForKey:@"name"];        self.pic_url = [aDecoder decodeObjectForKey:@"url"];    }    return self;}@end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

如果这里有100个属性,那么我们也只能把100个属性都给写一遍。

不过你会使用runtime后,这里就有更简便的方法。

下面看看runtime的实现方式:

#import "Movie.h"#import <objc/runtime.h>@implementation Movie- (void)encodeWithCoder:(NSCoder *)encoder{    unsigned int count = 0;    Ivar *ivars = class_copyIvarList([Movie class], &count);    for (int i = 0; i<count; i++) {        // 取出i位置对应的成员变量        Ivar ivar = ivars[i];        // 查看成员变量        const char *name = ivar_getName(ivar);        // 归档        NSString *key = [NSString stringWithUTF8String:name];        id value = [self valueForKey:key];        [encoder encodeObject:value forKey:key];    }    free(ivars);}- (id)initWithCoder:(NSCoder *)decoder{    if (self = [super init]) {        unsigned int count = 0;        Ivar *ivars = class_copyIvarList([Movie class], &count);        for (int i = 0; i<count; i++) {        // 取出i位置对应的成员变量        Ivar ivar = ivars[i];        // 查看成员变量        const char *name = ivar_getName(ivar);       // 归档       NSString *key = [NSString stringWithUTF8String:name];      id value = [decoder decodeObjectForKey:key];       // 设置到成员变量身上        [self setValue:value forKey:key];        }        free(ivars);    }     return self;}@end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

这样的方式实现,不管有多少个属性,写这几行代码就搞定了。怎么,还嫌麻烦,下面看看更加简便的方法:两句代码搞定。

我们把encodeWithCoder 和 initWithCoder这两个方法抽成宏

#import "Movie.h"#import <objc/runtime.h>#define encodeRuntime(A) \\unsigned int count = 0;\Ivar *ivars = class_copyIvarList([A class], &count);\for (int i = 0; i<count; i++) {\Ivar ivar = ivars[i];\const char *name = ivar_getName(ivar);\NSString *key = [NSString stringWithUTF8String:name];\id value = [self valueForKey:key];\[encoder encodeObject:value forKey:key];\}\free(ivars);\\#define initCoderRuntime(A) \\if (self = [super init]) {\unsigned int count = 0;\Ivar *ivars = class_copyIvarList([A class], &count);\for (int i = 0; i<count; i++) {\Ivar ivar = ivars[i];\const char *name = ivar_getName(ivar);\NSString *key = [NSString stringWithUTF8String:name];\id value = [decoder decodeObjectForKey:key];\[self setValue:value forKey:key];\}\free(ivars);\}\return self;\\@implementation Movie- (void)encodeWithCoder:(NSCoder *)encoder{    encodeRuntime(Movie)}- (id)initWithCoder:(NSCoder *)decoder{    initCoderRuntime(Movie)}@end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

我们可以把这两个宏单独放到一个文件里面,这里以后需要进行数据持久化的模型都可以直接使用这两个宏。

原创粉丝点击