ios Runtime 用法汇总
Runtime 简介
1、objective-C是一种消息类型的语言,既然是消息类型的语言,那么所应执行的代码由运行环境来决定,只有在运行时才会去查找所要执行的方法。
2、objective-C的重要工作由“运行期组件”来完成而非编译器来完成。使用面向对象所需的全部数据结构和函数都在运行期组件里。举例来说,运行期组件含有全部内存管理的方法。
3、objective-C是一种动态语言,所以静态语言在编译和链接时期做的事放到了运行期来处理。这种语言的有事在于:我们写代码时更加的方便灵活,可以动态的修改指定类中的方法或者属性,或者添加方法或者属性
运行时的用法
1)快速归档
当我们需要将一些本地信息进行持久化处理的时候,会将数据模型中的属性进行获取,并将属性名和属性值进行归档
使用案例:抽象一个用户信息模型(包含name,age,gender),创建一个用户模型进行归档
快速归档2)json转model
通过class_copyIvarList 函数将json转化为模型
使用案例:创建一个cat数据模型(包含cid、age)和一个json和model的方法,这个方法的核心代码如下
json转model将json进行赋值并进行模型的转化:
转化打印结果:
结果3)访问私有变量
当我们需要访问一个.m中的私有属性的时候,需要用class_getInstanceVariable和object_getIvar来获取我们想要的属性
使用案例:privateProperty类.h文件中暴露personName属性,.m中暴露phoneNumber和bodyData私有属性,在其他的类中获取bodyData属性值
需要被访问的赋值类调用函数
调用执行结果bodyData的信息
4)动态添加方法
使用场景:当前类中方法过多,如果都加载到内存中肯定会加重内存的负担,我们可以选择动态添加方法。
使用案例:当addSelector类中没有eat方法时,动态添加方法
动态添加 调用方法5)通过 block回调 直接调用手势识别的action
使用场景:当我们创建手势点击时,可以运用runtime机制,实现函数和相应式编程
使用案例:在当前的控制器中添加手势,实现点击
block回调调用方式:
调用点击控制器之后,会打印“点击------”
6)分类添加属性
使用场景:在创建的分类中,我们是可以创建属性和方法的,但是创建的属性是没有getter和setter方法的,我们可以用runtime将属性进行关联实现getter和setter方法。
使用案例:NSObject (property)这个类别里添加一个name属性,用runtime实现属性的setter和getter方法
关联调用方法
调用7)Method swizzling(方法交换“黑魔法”)
应用场景:系统自带方法功能不够用,给系统自带的方法扩展一些功能,并保存原有功能
应用案例:imageName:如果图片为空时,不会提示图片加载异常,当用“方法交换”添加的图片为空时,提示加载图片为空...
方法交换调用: UIImage *image = [UIImage imageNamed:@"123"];
其中@“123”图片为空
打印结果是:加载图片为空...
8)利用runtime热更新
背景:我是在公司进行技术分享runtime用法的时候CTO提出了问题:能不能利用runtime进行热更新?现在比较主流的热更新方式JSPatch做热更新行不行?
当时一下没反应过来,但是知道肯定是不行的,苹果爸爸对用户隐私这块抓的这么紧,而且17年的时候苹果爸爸已经对涉及到JSPatch的项目发出了警告-不移除就下架,但是自己并不太清楚JSPatch这种工具是如何实现热更新的,所以自己查了查相关的资料。
苹果的警告是针对使用了dlopen(),dlsym(),respondsToSelector,performSelector,method_exchangeImplementations()等反射函数用于动态调用OC API - 基于反射的热更新。通过远程下载的脚本使用这些函数达成改变app行为。
JSPatch的工作原理是:编写JavaScript代码,利用苹果的JavaScriptCore将代码转化为字符串,利用runtime对项目中的代码修改或者添加某些功能。这样的话如果黑客获取了用户的信息并上传到黑客的服务器,那么会对用户造成重大的安全问题。
游戏中的热更新技术:把脚本下载下来,让动态脚本调用游戏引擎提供的接口实现缺陷修复,与JSPath不同,动态脚本不能调用全部的原生代码,而是为游戏引擎提供的接口调用相应的功能。
所以综上,JSPatch已经被苹果爸爸彻底抛弃了,不要在想利用runtime去绕过苹果爸爸的审核。