JavaScriptCore引入后,js调用OC的方法有了新的实现方式。让一个类遵循一个JSExport的协议,将想要暴露的方法在JSExport协议中声明,即可在js中直接调用到OC的方法。
例如下面的代码:
|
|
但是这样的实现并不灵活,如果我有大量的类和其中的方法要在js中使用,那么我可能需要实现大量的JSExport协议,这样会导致项目中的代码量大大增加。于是想到了可以使用runtime动态创建这些协议,然后添加到class中。
1、首先让我们制作一个扩展JSExport的新协议,假设我们有一个Class class我们要导出的变量:
|
|
2、然后我们从类中读取方法列表和属性列表,并将它们添加到protocol中:
实例方法:
|
|
类方法:
|
|
属性:
添加属性的方法基本和添加方法相同,但是我们还需要获取每个属性的特性,并添加到协议中
|
|
3、将新协议添加到类中
|
|
4、然后理论上我们应该是可以在js中使用这个类中的方法了,接下来使用下面的代码测试下。
|
|
然后我们发现,js的执行抛了异常。为什么呢?我们的实现逻辑并没有问题。
这里查看JavaScriptCore源代码。
最后发现原因在与objCCallbackFunctionForMethod方法,改函数通过调用objCCallbackFunctionForInvocation返回了一个原生函数的指针JSObjectRef。objCCallbackFunctionForInvocation函数的调用语句如下:
|
|
这里使用了_protocol_getMethodTypeEncoding函数。到ObjcRuntimeExtras.h中看看函数的定义。
|
|
再到https://opensource.apple.com/source/objc4/objc4-551.1/runtime/objc-runtime-new.mm中找到了实现:
|
|
函数注释中写名了,Returns nil if the compiler did not emit any extended @encode data.所以我们只能在编译阶段创建好JSExport。
本文作者: ctinusdev
本文链接: https://ctinusdev.github.io/2017/08/05/CantnotCreateJSExportAtRuntime/
转载请注明出处!