APICloud 是优秀的跨平台开发的工具。它的模块化市场也很丰富,基本上能满足日常开发的所有需求。它里面有一个个人觉得很有意思的方法,就是api.require(),这个方法在返回一个js对象的同时也会满足这个js对象直接调用iOS原生下的同名方法,花了半天的时间,简单的模拟了这样的一个功能,下面为大致思路跟部分代码,如大神们有更好的思路,多多指教。
步骤1、先看一下自定义html页里面的简单逻辑

这里在js里直接初始化了一个api对象和创建了一个apiready方法。如果了解过APICloud的话,这个是APICloud的默认方法,api这个对象会提供丰富的方法来实现各种逻辑,这里为了模仿就简单的初始化了一个Object对象。apiready这个方法会在api这个对象完成初始化成功后调用;最终要实现的就是通过我们自定义的api对象创建如图所示的log对象,并且该log对象可直接调用原生下对于log类的原生同名方法。
步骤2、再看一下原生下的需要调用的实例的方法
在原生工程里创建一个“WSLApiWebLog”类,创建一个“log”的实例方法。

步骤3、创建WKWebView视图及搭建JS与OC桥接
仅仅是为了模仿apiCloud,本人将html里面的api.require这个方法放到了OC下进行了创建。

在webView加载完成的代理方法里添加上图逻辑,为html里的api js对象添加require方法,这里有个问题js报错问题,大致的意思是js在执行的时候返回了一个未知的类型,应该是api.require这个属性接受了一个function引起的,但是没有影响后面的逻辑,百度了一段时间,也没有思路,希望给予指点。
这里用到了两个比较重要的js方法:window.prompt和eval;
首次说一下window.prompt方法,因为需要api.require返回一个js对象,那么就需要WKWebView接受一个js同步方法,并在执行完原生逻辑后可反馈给js,因此这里调用了window.prompt方法。
那么,怎么接受的呢?
WKWebView 代理方法
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler

在WKWebView的代理方法里可以接受到这个同步方法,再方法的结尾的有一个回调completionHandler,它需要返回一个字符串;这里创建js需要用到的iOS实例并保存到 saveDynamicClassInstanceArr 数组里;这样我们可以在处理完原生逻辑后调用这个闭包,但是返回值需要的是一个字符串,创建什么字符串呢?
别忘了,api.require需要返回一个js对象,并且之前还有一个重要的js方法eval;eval是可以将字符串直接运行起来的js方法;这样的话,在WKWebView同步方法的completionHandler回调里传入一个初始化js对象的逻辑的字符串,然后在通过eval去执行这个字符串,那么api.require这个方法就返回了一个js对象了。
步骤4、创建一个什么样的初始化js对象逻辑的字符串?

不啰嗦,直接上代码,api.require的方法里是要传一个iOS类名字符串的,这个是一个简单的桥接类方法,接受的参数是由js端传过来的,这里直接去查找原生类下面的实例方法,然后根据js逻辑规则生成相对应的字符串。例子:{OCMethod:function(param){window.webkit.messageHandlers.initNative.postMessage}}。
window.webkit.messageHandlers 此方法区别与上面的window.prompt方法,它只管调用,不需要回调,触发原生执行部分逻辑即可,所以,这个方法很适合js对象调用OC下同名方法。
好了,到这儿 api.require方法就返回了一个与OC对象拥有同名方法名的js对象了。

步骤5、 调用apiready方法

这个方法可以在原生下api对象初始化逻辑完成后执行(适当调用的意思你认为什么时候可以了就行),在html里面的apiready就完成了调用。

步骤6、 原生实例执行相关方法
WKWebView 代理方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message

这里会获取对应的类名+方法名+参数,就可以执行了。
步骤7、测试结果
最后apiready方法里面的log js对象执行log方法 调用了iOS 下的 WSLApiWebLog 原生对象 log方法,并传进入一个json对象。

结尾:到这里基本的思路就讲完了,没有太复杂的逻辑,表达能力有限。希望对大家能有帮助,同时也接受大神们的批评指正,共同进步。