前言
如果需要WKWebView的JS交互描述,请查看本站的另一个文章:
本文主要记录一下UIWebView和JavaScript之间的交互!!由于iOS8之后,苹果推出了性能更加好的WKWebView,而WKWebView的交互与UIWebView的交互基本不一样!所以站长没有专注详细记录实现过程,只为项目经验及其他已经写好的博客做一个记录!!记录一下自己的认识!!
本文的内容来自:http://www.jianshu.com/p/dbddfc0eaa26
本文的学习过程
1.OC与JS间的直接交互方式!!
2.OC与JS间JavaScriptCore.framework来做交互!!(推荐)
1.OC与JS间的直接交互方式
直接调用,优势就是直接!适用于交互只有一两次的场景使用!!不需要导入框架!只要和H5前端规定好方法名和JS调用的URL名字就可以完成交互!!!
JS调用oc
(不知道Html和JS具体什么情况的同学,找前端过来看看,哈!)
js标签内添加跳转方法,然后在对应的触发位置(例如button)触发此方法。
function firstClick(){ window.location.href="lalalala://shareClick"; }
js会在UIWebview进行请求加载,这个时候,我们可以使用协议方法进行拦截,拦截后,使用响应的参数和约定的方法名来调用OC的代码!
oc 调用js
oc触发的代码如下:
NSString *textJS = @"showAlert('这里是JS中alert弹出的message 第一种方式')"; [_webView stringByEvaluatingJavaScriptFromString:textJS];
JS端应该写好这个showAlert的方法,如:
function showAlert(message){ alert(message); }
OC注入js方法:
//注入方法 NSString *jsfunction = @"function uiwebviewt(){alert(2);}"; [webView stringByEvaluatingJavaScriptFromString:jsfunction];
OC注入js对象:
NSString *jsobj = @"var testobjui = {'info':function(){alert('testobjui');}}"; [webView stringByEvaluatingJavaScriptFromString:jsobj];
到这里,直接调用就已经实现了。。。。
2.OC与JS间JavaScriptCore.framework来做交互!!(推荐)
我们实际应用的时候,其实会比直接调用的场景复杂得多!!除了互相调用写好的方法,有时候我们需要注入一些方法或者对象!!这个时候,我们需要用到iOS7.0公布使用的JavaScriptCore.framework。
这个框架有两个优势:
1.可以给js直观地植入方法或对象(推荐注入一个对象,对象有属性和方法);
2.编程被对象化。
JS调用OC
核心步骤:
JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
这句代码是捕捉到当前webView的上下文,可以想象是html的script便签内环境!!!
使用前,要给项目导入JavaScriptCore.framework库。
web中的js方法
这个JS只是写了secondClick方法,但是,你要注意到,它并没有share方法,而这个share方法就需要我们OC注入进去。
注入前,先介绍几个javascriptcroe重要的类和一个重要的协议(不遵循这个协议,方法不会暴露在JS的context里)
JSContext
JS执行的环境,同时也通过JSVirtualMachine管理着所有对象的生命周期,每个JSValue都和JSContext相关联并且强引用context。
JSValue
JS对象在JSVirtualMachine中的一个强引用,其实就是Hybird对象。我们对JS的操作都是通过它。并且每个JSValue都是强引用一个context。同时,OC和JS对象之间的转换也是通过它,相应的类型转换如下:
Objective-C type | JavaScript type --------------------+--------------------- nil | undefined NSNull | null NSString | string NSNumber | number, boolean NSDictionary | Object object NSArray | Array object NSDate | Date object NSBlock (1) | Function object (1) id (2) | Wrapper object (2) Class (3) | Constructor object (3)
JSExport(协议)
如果JS对象想直接调用OC对象里面的方法和属性,那么这个OC对象只要实现这个JSExport协议就可以了。
现在我们来实现OC通过javascriptcore注入JS方法
这个图里,有两步是比较重要的!!
1.获取context,这个是固定的写法!记着就好了!
2.给context的一个键添加一个block,这个block就是你注入的方法,这个键就是你的方法名!
通过JScontext直接调用share方法,从JSValue中取值
oc 调用js(调用web已写好的showAlert方法)
JSContext *context = [_webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; //oc 调用 js NSString *textJS = @"showAlert('这里是JS中alert弹出的message')"; [context evaluateScript:textJS];
下面,我们来使用更规范地交互:(核心:JSExport)
上面是方法的直接注入和直接调用,下面我们来通过注入对像 和 调用对象方法
凡是添加了JSExport协议的协议,所规定的方法,变量等 就会对js开放,我们可以通过js调用到
首先在html中创建对象,定义方法
在JS代码里,使用了一个叫TestJSobject的对象, 这个对象有三个方法。
无参方法 TestJSobject.TestNOParameter(); 有一个参数的方法 TestJSobject.TestOneParameter(TestJSobject.name); 有两个参数的方法 TestJSobject.TestTwoParameterSecondParameter(TestJSobject.name,TestJSobject.age);
现在,我们一步步给JS添加这个对象
1.创建OC类,添加协议,实现协议方法
注意,这里写了一个协议,这个协议必须要继承JSExport,协议的方法会在web的context里面暴露出来!!!
实现协议的方法
2.获取JScontext,注入对象多JSContext,供前端调用
在UIWebView的协议方法 -(void)webViewDidFinishLoad:(UIWebView*)webView 添加以下的代码!!
//js对象调用,创建对象 JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; TestJSobject *test = [TestJSobject new]; context[@"TestJSobject"] = test;
到这里,我们已经成功注入了对像!!!
OC调用JS
//同样我们也用刚才的方式模拟一下js调用方法 NSString *jsStr1=@"TestJSobject.TestNOParameter()"; [context evaluateScript:jsStr1];
总结
上面讲述了在使用UIWebView时两种JS和OC的交互。1.直接交互!2.通过JavaScriptCore做交互!站长推荐使用第二种方式,更加方便,更加符合我们面向对象的设计思维!!