/ iOS 开发

解决 JSPatch 打补丁出现 ReferenceError: Can't find variable: ocat34 错误

解决 JSPatch 打补丁出现 ReferenceError: Can't find variable: ocat34 错误

JSPatch 是一个非常棒的热修复方案。虽然在去年的时候,苹果为了防止动态下发脚本被滥用,曾经禁止了包含 JSPatch 的 App 上架,不过后来 JSPatch 作者经过和苹果的沟通,现在只要接入 JSPatch 平台,就可以继续使用 JSPatch 打补丁了。

最近新版本上线的时候遇到一个 crash,使用 JSPatch 平台的代码转换工具将 Objective-C 代码转换成 js 代码后,本地测试的时候遇见一个报错:

JP: 脚本执行错误: e: ReferenceError: Can't find variable: ocat34

Google 了下这个问题,没有找到有价值的信息,GitHub 上也有这个 issue,但是还是 Open 状态。看来只能自己调试了,JSPatch 补丁调试起来也并不困难,可以参考官方 JS 断点调试

开启 JSPatch 本地测试模式,当程序运行到 js 脚本这段逻辑的时候,在 Safari 浏览器中就可以找到 JSContext 的调试面板。在这里可以给 js 代码打断点,一步一步调试。

调试过程中发现在判断一个枚举类型的时候会报 ReferenceError: Can't find variable: ocat34 这个 error。

if (attention.__c("recommendType")() == PNAttentionTypeActivity) {} else {}
            }

难道是 JSPatch 中无法识别我们的枚举类型?查看了 JSPatch 的文档

常量与宏 Objective-C 里的常量不能直接在 JS 上使用,可以直接在 JS 上用具体值代替,或者在 JS 上重新定义同名的全局变量:

//js
var UIRectEdgeNone   = 0,
    UIRectEdgeTop    = 1 << 0,
    UIRectEdgeLeft   = 1 << 1,
    UIRectEdgeBottom = 1 << 2,
    UIRectEdgeRight  = 1 << 3

于是我在 js 代码中把 PNAttentionTypeActivity 这个值改成了原始的 NSInteger 值,就不会报错了。另外使用全局定义的 static NSString 时,也会报这种错误,解决办法就是使用原始值。当然更好的做法,是在 JS 中定义同名的全局变量。