学习笔记1:归档解档、runtime

系统类型

1.归解档字符串

两者都需要先拼出文件路径:
归档

NSString *path = [docPath stringByAppendingPathComponent:@"myStr"];
[NSKeyedArchiver archiveRootObject:@"我是字符串" toFile:path];

解档

NSString *path = [docPath stringByAppendingPathComponent:@"myStr"];
NSString *str = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

2.归解档数组

两者都需要先拼出文件路径:
归档

NSString *path = [docPath stringByAppendingPathComponent:@"myArray"];
[NSKeyedArchiver archiveRootObject:@[@"元素1", @"元素2", @"元素3" toFile:path];

解档

NSString *path = [docPath stringByAppendingPathComponent:@"myArray"];
NSString *str = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

3.归解档字典

两者都需要先拼出文件路径:
归档

NSString *path = [docPath stringByAppendingPathComponent:@"myDic"];
[NSKeyedArchiver archiveRootObject:@{key:value};

解档

NSString *path = [docPath stringByAppendingPathComponent:@"myDic"];
NSString *str = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

自定义类型(两种方法)

例:现有一student学生类具有以下属性:

@property (nonatomic) NSString *name;
@property (nonatomic) NSString *sex;
@property (nonatomic) NSUInteger age;
@property (nonatomic) NSString *school;
@property (nonatomic) BOOL marry;
@property (nonatomic) NSString *className;
@property (nonatomic) NSString *favor;
@property (nonatomic) NSString *skill;
@property (nonatomic) NSString *score;

要想对该学生类实现归档和解档,就一定要实现<NSCoding>协议,该协议中只有两个方法:即要归档的属性和要解档的属性。

方法一:

归档

- (void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:_name forKey:@"name"];
    [aCoder encodeInteger:_age forKey:@"age"];
    [aCoder encodeObject:_sex forKey:@"sex"];
    [aCoder encodeObject:_favor forKey:@"favor"];
    [aCoder encodeObject:_score forKey:@"score"];
    [aCoder encodeObject:_skill forKey:@"skill"];
    [aCoder encodeObject:_school forKey:@"school"];
    [aCoder encodeObject:_className forKey:@"className"];
    [aCoder encodeBool:_marry forKey:@"marray"];
}

对应的解档

- (instancetype)initWithCoder:(NSCoder *)aDecoder{
    if (self = [super init]) {
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.age = [aDecoder decodeIntegerForKey:@"age"];
        self.sex = [aDecoder decodeObjectForKey:@"sex"];
        self.favor = [aDecoder decodeObjectForKey:@"favor"];
        self.score = [aDecoder decodeObjectForKey:@"score"];
        self.skill = [aDecoder decodeObjectForKey:@"skill"];
        self.school = [aDecoder decodeObjectForKey:@"school"];
        self.className = [aDecoder decodeObjectForKey:@"className"];
        self.marry = [aDecoder decodeBoolForKey:@"marray"];
    }
    return self;
}

由于方法一过于单一,遇到属性过多的情况时不能轻松解决,所以需要使用另一种方法来解决(runtime).

方法二:Runtime机制

需要引入runtime库#import <objc/runtime.h>
归档

- (void)encodeWithCoder:(NSCoder *)aCoder{
    // Ivar: 成员变量
    // class_copyIvarList: 拷贝参数一的类的所有属性列表出来,第二参数中会被存入列表中的元素数量
    unsigned int outCount = 0;
    Ivar *varList = class_copyIvarList(self.class, &outCount);
    for (int i = 0; i < outCount; i++) {
        // 从列表中获取每一个成员变量
        Ivar var = varList[i];
        // 获取成员变量的名字
        const char *name = ivar_getName(var);
        // C字符串 -> OC字符串
        NSString *propertyName = [NSString stringWithUTF8String:name];
        NSLog(@"%@", propertyName);
        // KVC
        id value = [self valueForKey:propertyName];
        // 归档
        [aCoder encodeObject:value forKey:propertyName];
    }
    // C语言在用完之后手动进行释放
    free(varList);
}

解档

- (instancetype)initWithCoder:(NSCoder *)aDecoder{
    if (self = [super init]) {
            // 1.复制属性列表
        unsigned int outCount = 0;
        Ivar *varList = class_copyIvarList(self.class, &outCount);
            // 2.for循环对每个成员变量进行操作
        for (int i = 0; i < outCount; i++) {
            // 3.获取成员变量名,转换成OC的名字
            Ivar var = varList[i];
            const char *name = ivar_getName(var);
            NSString *pName = [NSString stringWithUTF8String:name];
            // 4.通过属性名解档出对应的值
            id value = [aDecoder decodeObjectForKey:pName];
            // 5.通过KVC方式,把值存储到对应的属性中
            [self setValue:value forKey:pName];
        }
        
        free(varList);
    }
    return self;
}

可以将description、归档、解档定义为宏。以下以description为例,归档和解档同样定义。

// 宏中的‘\’作用是换行,表示接下来一行也是宏的内容
#define kDescription \
- (NSString *)description{\
    NSMutableString *str = [NSMutableString new];\
    unsigned int outCount = 0;\
    Ivar *varList = class_copyIvarList(self.class, &outCount);\
    for (int i = 0; i < outCount; i++) {\
        Ivar var = varList[i];\
        const char *name = ivar_getName(var);\
        NSString *pName = [NSString stringWithUTF8String:name];\
        id obj = [self valueForKey:pName];\
        [str appendFormat:@"%@:%@", pName, obj];\
    }\
    free(varList);\
    return str;\
}

runtime为系统类添加属性

例:为一个button添加一个name属性,用来存储button的名字。

创建一个UIButton的分类UIButton+Custom,在.h声明一个名字属性
@property (nonatomic) NSString *name;
.m文件中引入#import <objc/runtime.h>,实现setget方法:

- (void)setName:(NSString *)name{
    // 绑定参数3到参数1的键-参数2上, 内存管理的方式是参数4
    // 参数2是方法的指针地址,每个方法的指针地址是唯一的
    objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)name{
    // 获取参数1中key是当前方法的指针对应的值
    // _cmd 可以获取所在的方法指针
    return objc_getAssociatedObject(self, _cmd);
}

更换类型

runtime可以更换对象的类型(OC无法实现的时候)

例:将tableView的类型转换为第三方TPKeyboardAvoidingTableView类型

// 使用runtime替换tableView的类型
// 把参数一的类型变成参数2的类型
object_setClass(self.tableView, [TPKeyboardAvoidingTableView class]);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容

  • 对于从事 iOS 开发人员来说,所有的人都会答出【runtime 是运行时】什么情况下用runtime?大部分人能...
    梦夜繁星阅读 3,674评论 7 64
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,636评论 0 9
  • 窗外的小雨 打湿了世界 却未淋湿我的衣裳 打开了满校园五彩的伞花 却没溶解弥漫着的芬芳 微风中 雨点洋洋洒洒 新绿...
    北纬十二度阅读 209评论 0 0
  • 01 有人说,我们努力了那么久,不过就是过上了普通人的生活。 我想,说这句话的人,怎么说至少算是个努力的人,至于为...
    左小丘丘故事机阅读 435评论 0 1
  • 写在前面,这个是一个小说,可以看做小说的片段吧。第一次尝试两个视角的转换,也许不会看晕吧。 “师尊,你为何对我这么...
    小荷初露阅读 147评论 0 0