本文可能只适合新手。基于Cordova 4.0+,讲的比较肤浅,主要是记录一下这段时间对Cordova的学习。文笔比较不好,如有错误欢迎指正,欢迎探讨。
总结在前:
OC调用js
一、webview 调用 stringByEvaluatingJavaScriptFromString 方法
注:同步方法,可能会阻塞UI
二、JavaScriptCore做js交互
JSContext *context = [self.webview valueForKeyPath:@“documentView.webView.mainFrame.javaScriptContext"]
[context evaluateScript:XXXX];
js调用OC
一、利用js打开iFrame方式发假请求,webview进行拦截
(默认方式)iframe的方法:添加iframe到html元素中,并设置iframe的src为指定gap://ready(相当于发假的URL请求),触发Native侧UIWebview:shouldStartLoadWithRequest的方法。拦截住此次请求后再调用JS代码向JS侧发起取参数的操作,取回后Native再进行处理。
注:为什么不用document.location: 如果我们连续 2 个 js 调 native,连续 2 次改 document.location 的话,在 native 的 delegate 方法中,只能截获后面那次请求,前一次请求由于很快被替换掉,所以被忽略掉了
二、JavaScriptCore: 在webViewDidFinishLoad完成载入后,对上下文进行设置
JSContext *context = [self.webView valueForKeyPath:”documentView.webView.mainFrame.javaScriptContext"]
context[@"share”] = ^(){….} //设置share 方法
一、简单讲下什么是Cordova
Apache Cordova是一个开源的移动开发框架。允许你用标准的web技术-HTML5,CSS3和JavaScript做跨平台开发。 应用在每个平台的具体执行被封装了起来,并依靠符合标准的API绑定去访问每个设备的功能,比如说:传感器、数据、网络状态等。(摘自官网)
同样的移动开发框架,还有react-native, weex等等。这里不做比较和讨论了。
二、讲下这篇文章的背景
我们今天要讲的,不是如何利用web技术去开发app。
而是底层最核心的代码,native和js的交互。
现如今,Hybrid App非常盛行。我开发的工程也是Hybrid App。注重用户体验,且变动较少的页面,使用Native开发。需要经常迭代的,安卓iOS通用的页面,就使用H5开发。而Native和H5的交互,我们使用的是Cordova工程的部分代码,也就是比较核心的代码,诸如CDVViewContoller等。
举个例子:某公司的考勤页面,是H5页面。在自己公司的App打开这个页面,如果要请假时需要填写backup的同事,此时选择同事是调用App Native本地存储的通讯录数据。这里就涉及到了JS与Native的相互调用和数据的传递。
三、整体的流程
1、利用CDVViewController(或是扩展的类),去加载某个H5链接。
2、该H5页面上某个按钮的点击事件需要请求Native插件。
(由于我们项目对CDVViewController又进行了一层封装,所以插件的加载,JS的注入,不需要对Cordova核心代码进行改动,如config.xml)
(--流程基本是通过断点打出来看的--)
四、具体是如何交互的,底层机制又是什么?
(JavaScriptCore也是交互的一种方式,但不在本章里讨论 )
1、JS如何调用Native?
(默认方式)iframe的方法:添加iframe到html元素中,并设置iframe的src为指定gap://ready(相当于发假的URL请求),触发Native侧UIWebview:shouldStartLoadWithRequest的方法。拦截住此次请求后再调用JS代码向JS侧发起取参数的操作,取回后Native再进行处理。
xmlHttpRequest的方法:
execXhr.open('HEAD', "/!gap_exec?" + (+new Date()), true);
execXhr.setRequestHeader('cmds', iOSExec.nativeFetchMessages());
Native侧UIWebview:shouldStartLoadWithRequest的方法,判定为/!gap_exec来拦截,并从头部取得插件的具体参数
保留该方式的原因:
// XHR mode does not work on iOS 4.2, so default to IFRAME_NAV for such devices.
// XHR mode’s main advantage is working around a bug in -webkit-scroll, which
// doesn’t exist in 4.X devices anyways
(iOS5.x版本因为 -webkit-scroll的IFRAME有BUG,则推荐使用)
因为我们项目现在都是支持iOS 7+,所以采用的都是iframe方式。
2、Native如何执行JS?
UIWebView 有一个这样的方法 stringByEvaluatingJavaScriptFromString
3、底层机制是怎么样的?
底层机制主要是结合1、2两种方式,形成一种一来一往的交互(可以看上述流程图)。
与普通调用1、2两种方法相比较,最核心的点在于:
1、Cordova在JS侧与Native侧均使用了队列来保存互相调用的请求,并生成了callbackid能及时找到与此次请求相关的上下文参数等等。
2、CDVPlugin、CommandDelegate等可以很好的开发插件。注入插件和js的话看个人,可以在继承CDVViewController里面去做。
五、具体的插件开发是什么样的
1、生成cfg文件(主要是对插件的描述)
2、生成.js文件(主要是供H5开发人员可以直接调用)
3、继承CDVPlugin的类去写插件类,有模板可仿照。
具体可看官网 http://cordova.axuer.com/docs/zh-cn/latest/guide/platforms/ios/plugin.html
——————————————————————
参考文章:https://www.jianshu.com/p/e74bc7abac8d (是讲述js与OC调用的,一个系列的,还不错)
http://blog.csdn.net/u011417590/article/details/50895734(是讲述Cordova核心类CDVViewController源码的)
http://blog.csdn.net/Linux7985/article/details/53022371 (相对清晰一点,我的结构也是模仿该篇的,可惜版本貌似比较老了)
http://blog.csdn.net/lq83623/article/details/42478223 (讲的也比较好,但下面的结构图大部分看不懂)
https://www.jianshu.com/p/21477a20707a (主要是插件开发相关)