Android iOS热修复,细说热修复(一),体验如何线上快速修复APP!

本文详细介绍了热修复的概念及其在iOS中的应用,特别是在紧急修复线上bug时的重要性。重点讲解了JSPatch的工作原理,包括DEFINECLASS、OVERRIDE_METHOD、JPFORWARDINVOCATION等关键步骤,以及如何通过JavaScript与Objective-C交互实现方法替换。此外,还提供了JSPatch的实战案例,展示了其在iOS热修复中的实际运用。
摘要由CSDN通过智能技术生成

什么是热修复?首先我们先来还原一下场景:

客服MM:用户反馈生产版本出现crash问题了,很严重没法用,怎么办,怎么办?

程序猿GG:测试组确认问题后,我们修复Bug,测试验证完成,打包发布。

客服MM:用户需要多久能下载新包呢?

程序猿GG:至少3天。

客服MM:额,这个.....

这个时候大家都会想,如果能够马上修复线上版本bug该多好啊。想法没毛病,热修复技术就是在这种场景下发展并普及的。

热修复是一种App客户端快速修复bug方法,通过后台下发代码,可以在App不发布新版本的情况下修复bug。在2015年的时候国内开始流行起来,在2017年3月被苹果的一封警告信推上了风口浪尖。

【基本原理】

后台下发代码(Patch包),App加载patch包,通过patch里的数据分析,查找到有问题的Method方法进行替换。替换是APP运行时直接调用新Method’方法执行,从而避免了bug的影响。

0b31510a54be8b463922236d240f439d.png

(图一)

【IOS热修复】

15年项目上在选择方案时,基于当时市面上比较流行的2种方案JSPatch和WaxPatch进行了对比。主要从性能、功能、维护成本等方面综合考虑。因为lua语言没有JS语言普及程度高,而且WaxPatch框架现在已经停止维护了,而JSPatch框架还在持续不断的更新,因此IOS热修复方案我们选择JSPatch。

6144d25ed965cd2b06afbaf5ec88a950.png

JSPatch的设计原理是利用了OC语言的动态特性,动态修改类的方法达到修复bug的目的。在介绍如何进行类方法替换之前,我们先来熟悉几个名词解释:Class、SEL、IMP,有助于我们理解方法替换。

Class在OC中是一个objc_class的结构体指针,定义如下:

74dcf881fb00cf957ef342f7ad160c64.png

322ad0a77c0dd858e48aaf78fde30a70.png

图2

我们知道OC中每个类都有一个isa的指针,指向类对象的类【元类metaclass】。通过isa指针能找到对象所属的类,类结构体里保存着所有的信息,如父类、类名、类成员变量、类方法、协议链表等。类方法都存储在objc_method_list链表中,我们从图2中可以看到链表中存储的objc_method对象,包括SEL(selector)方法选择器,表示为方法的名称;char*存储的是参数类型,包括方法的返回值类型和入参类型;IMP(implement)是一个函数指针,存储方法具体实现代码块的地址,可以像普通C函数调用一样使用IMP。

一、IOS方法替换原理

OC上所有方法的调用/类的生成都通过 Objective-C Runtime 在运行时进行,我们可以通过类名/方法名反射得到相应的类和方法。

d66ac37e5efd6730e324eea28a201a2f.png

二、JSPARCH和OC交互原理

回过头来再来看看JSPatch是如何进行工作的。JSPatch主要语言是JS脚本,利用IOS系统提供的JavaScriptCore.framework库执行JS脚本,可以调用在JSContext中预先定义的方法。

1.DEFINECLASS方法

21c4f975c0a29175f8b3429fbc094f4f.png

我们使用热修复就是为了要替换有Bug的方法,所以JS脚本中首先要定义好需要替换方法的类名、方法名,还有具体的方法实现过程。在OC端加载JSPatch的时候,会进行JPEngine的初始化,在初始化函数中有定义_OC_defineClass桥接函数。当js端执行_OC_defineClass方法时,就会触发OC的桥接函数调用。

▪ defineClass方法中能获得类名、方法名(如果有实现协议也能获得)。

▪通过NSClassFromString获得类对象,然后根据类对象和方法名获取到IMP。

▪同时返回{className:class}值给JS端。

2.OVERRIDEMETOD方法

f66fb9f9a51fcfdd9c9a6cc7c3ae5f50.png

OC从JS端脚本中获取到待替换的方法后,会判断app中是否有实现该方法,如果实现了就会执行overrideMethod函数。

▪overrideMethod把原始方法的IMP设置为_objc_msgForward,如果方法的返回值为特殊的struct类型(如:CGRect/CGRange)则设置为_objc_msgForward_stret,方法的调用会走消息转发流程。

▪添加新方法ORIG+方法名指向原始实现的IMP,保存原始方法。

▪添加JPForwardInvocation指向新的自定义IMP。

▪添加ORIGForwardInvocation指向原始的IMP。

3.JPFORWARDINVOCATION方法

上面提到了我们用JPForwardInvocation替换了原生的消息转发。替换的目的,是利用了IOS消息转发机制来实现一个通用的IMP,任意方法任意参数都可以通过这个IMP中转,拿到方法的所有参数回调JS的实现。在forwardInvocation中会有一个NSInvocation对象,保存了方法调用的所有参数值。

▪JPForwardInvocation读取传入的NSInvocation对象所有参数。

▪根据实际参数类型转换成OC类型。

▪把参数组装成一个数组返回给JS端。

▪如果转发的方法和JS脚本方法不匹配,调用ORIGForwardInvocation走原有的流程。

4._METHODFUNC()函数

JS脚本所有的方法调用都通过__c()函数,根据当前对象类型判断进行不同操作,_methodFunc()就是把相关信息转给OC,OC用Runtime接口调用相应方法的核心。

89b405767a9fdced0e79e521b47cf352.png

_OC_callI负责调用实例方法,_OC_callC负责调用类方法。

通过这两个函数调用,完成了JS端替换方法实现中调用OC对象或方法的过程。

5.CALLSELECTOR方法

JS端调用OC方法时,有时会出现JS类型和OC类型不一致的问题,通过此方法进行参数类型、返回值类型的转换和处理。

▪J将JS封装的对象进行拆分,得到OC对象。

▪J根据类名和方法名得到对应的Class对象和SEL。

▪J根据返回值类型,封装OC对象{className:cls,obj:obj}返回JS端

三、JSPATCH案例

71c636d31e6e366ade51420241c9c6dd.png

本文介绍了热修复的基本原理、IOS热修复的原理与方法,并进行了实战案例演示。我们会继续跟新关于ANDROID热修复的内容,请继续关注!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值