博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
玩转iOS开发:装逼技术RunTime的应用(三)
阅读量:6623 次
发布时间:2019-06-25

本文共 3504 字,大约阅读时间需要 11 分钟。

文章分享至我的个人技术博客:https://cainluo.github.io/15074742481003.html


在上一章节里晓得了怎么在Category里关联对象, 以及利用RunTime转换模型的时候预防了三种转换时的情况, 如果没有去看的朋友可以到看看.

转载声明:如需要转载该文章, 请联系作者, 并且注明出处, 以及不能擅自修改本文.


利用Runtime归档

在以前我们在使用归档的时候都会有一个烦恼, 就是写的太多, 不信? 我们来声明一个对象:

#import 
@interface RunTimeCoderModel : NSObject
@property (nonatomic, copy) NSString *cl_name;@property (nonatomic, copy) NSString *cl_height;@property (nonatomic, copy) NSString *cl_age;@end复制代码

常规归档的写法:

- (void)encodeWithCoder:(NSCoder *)aCoder {        [aCoder encodeObject:_cl_name                  forKey:@"name"];    [aCoder encodeObject:_cl_height                  forKey:@"height"];    [aCoder encodeObject:_cl_age                  forKey:@"age"];}复制代码

常规解档的写法:

- (instancetype)initWithCoder:(NSCoder *)aDecoder {        self = [super init];        if (self) {                self.cl_name   = [aDecoder decodeObjectForKey:@"name"];        self.cl_height = [aDecoder decodeObjectForKey:@"height"];        self.cl_age    = [aDecoder decodeObjectForKey:@"age"];    }        return self;}复制代码

现在看着好像也不怎么样, 但在实际开发中, 我们要写的属性可不是只有这三个, 如果遇到变态的, 有上百个那怎么办呢?

逐个逐个去写么? 万一写完之后突然要改属性怎么办? 逐个去改? 这样子就会大量的浪费我们的时间, 这是不明智的写法.

回想一下, 每个类都有一个isa的结构体指针, 里面可以拿到所有的每个类的信息, 那我们是否可以通过这个特性, 来给归档解档操作一番呢? 试试看:

RunTime归档的写法:

- (void)cl_runtimeEncoderWithCoder:(NSCoder *)coder {        unsigned int count = 0;        Ivar *ivarList = class_copyIvarList([self class], &count);        for (int i = 0; i < count; i++) {                Ivar ivar = ivarList[i];                const char *name = ivar_getName(ivar);                NSString *key = [NSString stringWithUTF8String:name];                id value = [self valueForKey:key];                [coder encodeObject:value                     forKey:key];    }        free(ivarList);}复制代码

RunTime解档写法:

- (void)cl_runtimeDecideWithCoder:(NSCoder *)decoder {        unsigned int count = 0;        Ivar *ivarList = class_copyIvarList([self class], &count);        for (int i = 0; i < count; i++) {                Ivar ivar = ivarList[i];                const char *name = ivar_getName(ivar);                NSString *key = [NSString stringWithUTF8String:name];                id value = [decoder decodeObjectForKey:key];                [self setValue:value                forKey:key];    }        free(ivarList);}复制代码

最终的使用:

- (void)encodeWithCoder:(NSCoder *)aCoder {            [self cl_runtimeEncoderWithCoder:aCoder];}- (instancetype)initWithCoder:(NSCoder *)aDecoder {        self = [super init];        if (self) {            [self cl_runtimeDecideWithCoder:aDecoder];    }        return self;}复制代码

最终的效果:

这的确是可行的, 这样子我们就把这个写成一个通用的类, 并且遵守<NSCoding>协议, 就可以把所有继承与NSObject的类全部一次性归档.

在这里我就不对归档和解档的方法进行封装了, 都写在RunTimeCoderController这个控制器上, 有想法的朋友可以自行进行封装, 这样子就可以抽成一个通用类.


RunTime黑魔法

前段时间搜了一下关于RunTime的一些博客, 发现有很多人都说RunTime黑魔法, 那什么是黑魔法?

  • 简单的来说, 其实就是进行方法交换.
  • 我们都知道, 在Objective-C中调用一个方法, 其实是向一个对象发送消息, 而查找消息的唯一依据就是selector的名字, 利用Objective-C的动态特性, 我们可以实现在运行时偷偷的换掉selector对应的方法实现.
  • 而我们也逗知道, 每一个类都有一个方法列表, 存放着方法的名字和方法实现的映射关系, selector其实就是方法名, 而IMP类似函数指针, 指向具体的Method实现, 通过selector就可以找到对应的IMP.

  • 交换方法的实现方式
    • 利用method_exchangeImplementations来交换两个方法的实现
    • 利用class_replaceMethod替换方法的实现
    • 利用method_setImplementation来直接设置某个方法的IMP

除了我们在演示里写过的代码, 在实际上又是怎么运用呢? 这里收集到了几种场景:

  • 替换ViewController的生命周期方法
  • 解决集合类的获取索引, 添加, 删除元素越界崩溃的问题
  • 防止按钮重复暴力点击
  • 全局更换控件初始化的效果
  • App的热修复
  • App空数据时的占位图工具类封装
  • 全局修改UINavigationBarBackButtonItem

代码这里就不写了, 想详细了解的朋友可以到下面的文章去了解.


推荐文章


工程地址

项目地址: https://github.com/CainRun/iOS-Project-Example/tree/master/RunTime/Five


最后

码字很费脑, 看官赏点饭钱可好

你可能感兴趣的文章
s17data01
查看>>
kubernetes1.9.1 集群
查看>>
java set and get 用法
查看>>
linux笔记1-1
查看>>
less及编译工具介绍
查看>>
干货满满,腾讯云+社区技术沙龙 Kafka Meetup 深圳站圆满结束
查看>>
IP访问控制列表(ACL)
查看>>
MPLS ×××案例
查看>>
Jmeter-发送JDBC请求
查看>>
LVS DR模式搭建 keepalived + LVS
查看>>
dubbo源码分析-负载均衡
查看>>
OCP 052考试新题库收集整理-第20题
查看>>
决心书
查看>>
一统江湖的大前端(3) DOClever——你的postman有点low
查看>>
Java 初始化执行顺序
查看>>
云栖大会上发布了哪些移动研发新利器?
查看>>
《黑客免杀攻防》读书笔记-软件逆向工程(6) switch-case分支
查看>>
根据自己的应用范围选择合适
查看>>
day6作业--游戏人生完善
查看>>
金字塔思维
查看>>