iOS开发 怎么实现js调取oc中的方法

JavaScript015

iOS开发 怎么实现js调取oc中的方法,第1张

我们要做的有如下几件事情:

首先:通过webview加载一个本地html文件

[self.myWebView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"html"]isDirectory:NO]]]

其次:我们要在我们的OC代码里面注册JS方法

- (void)h5callApp

{

//获取该UIWebview的javascript执行环境。

JSContext *context = [self.myWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]

context.exceptionHandler = ^(JSContext *con, JSValue *exception) {

NSLog(@"%@", exception)

con.exception = exception

}

context[@"h5CallApp"] = ^() {

NSLog(@"+++++++Begin Log+++++++")

NSArray *args = [JSContext currentArguments]

for (JSValue *jsVal in args) {

NSLog(@"%@", jsVal)

}

JSValue *this = [JSContext currentThis]

NSLog(@"this: %@",this)

NSLog(@"-------End Log-------")

}

}

要保证本地的html里面有h5CallApp这个方法哦。

这就是刚刚上述博客里面提到的方法,是不是看上次很简单的样子。

But

我运用到我们项目里面的时候,死活不能调用该方法,why?我厚着脸皮问了我们的帅哥安卓开发,得知他们里面有这一样一行代码

webView.addJavascriptInterface(new JSInvoke(), "test")

看上去第一眼的感觉是不是累似注册了一个东西,可是我找了好多博客我没有找到我们IOS类似的啊,着急啊着急。

意外的意外,伟大的github上面就是资源多,我在上面找到一个EasyJSWebViewSample这样一个开源项目,里面有一句

MyJSInterface* interface = [MyJSInterface new]

[self.myWebView addJavascriptInterfaces:interface WithName:@"MyJSTest"]

是不是感觉和安卓里面的那个注册类似的,没错,太开心了。

最后的最后,你以为结束了,NO!

该Demo里面的html有空的小朋友可以看一下。

由于项目需求我们是3个参数,在该demo里面执行拿到第一个参数,该demo就运行出错,提示我们数组越界了,在这里真的浪费了好多时间,后来发现他们的demo里面调用两个参数的方法在JS里面声明的方法与OC里面真正的实现方法有点差入,比如OC里面定义的方法

- (void) h5CallApp: (NSString*) param And2: (NSString*) param2 And3: (NSString*) param3

在html里面只能写成

MyJSTest.h5CallAppAnd2And3("param1","param2","param3")。

是不是觉得不可思义,最后我整体看了一下代码,里面好像有这一段在注入JS的时候有用到的

inject: function (obj, methods){\\

window[obj] = {}\\

var jsObj = window[obj]\\

\\

for (var i = 0, l = methods.lengthi <li++){\\

(function (){\\

var method = methods[i]\\

var jsMethod = method.replace(new RegExp(\\":\\", \\"g\\"), \\"\\")\\

jsObj[jsMethod] = function (){\\

return EasyJS.call(obj, method, Array.prototype.slice.call(arguments))\\

}\\

})()\\

}\\

}

这个好像是替换方法的,原谅我的无知啊,我也是没看懂,仅仅是感觉与猜测,勿喷我,我真的怕被喷。

最后的最后,JS的那边的开发肯定是不会为了将IOS与安卓开发做区分写代码的,所以我只能在注入JS完成后加了这么一句

[webView stringByEvaluatingJavaScriptFromString:@"test.h5CallApp=test.h5CallAppAnd2And3"]

这句话的作用是替换JS里面的方法的。

目前iOS项目中 Webview 几乎都会用到,iOS 8 之前使用UIWebView,iOS 8 之后 Apple 就不推荐使用了,目前已经放弃了,如果项目中存在就无法上架了,需要转为WKWebView了,说实话 UIWebView 是有性能上的缺陷,内存优化不够友好等,但是不得不说这是老的iOS开发人员用的最熟练熟悉的了,用起来得心应手。非迫不得已还真不愿转到WKWebView。好吧,既然已经这样了,又何必苦苦单恋一支花呢?

看了网上教程很多,自己使用小结一下,简单易用,本文适用于菜鸟级开发,废话不说了,

最主要的方法:发送消息

注意:对象名和方法名jumpUserProtocol名字的一致,参数可以是常用的NSArray,NSDictionary等类型,先说下在这个Demo中其实没用上,用的方法名判断的。

注意: addScriptMessageHandler

name为方法名 ,和JS 中的保持一致,添加脚本,相当于给Webview添加一个监听,有这个功能来处理JS。

在WKScriptMessageHandler代理方法中处理回调,实现自己的逻辑。

上面就是JS调用OC原生实现。

这个其实很简单,就一个方法:

参考如下内容:

主要有两种方法。一种是使用系统的浏览器组件(IOS中的UIWebView和Android中的WebView),另一方法就是使用整合好的JavaScript引擎。

使用系统的浏览器组件比较容易实现但是更复杂,效率也低。 WebView提供了 addJavascriptInterface 把Java classes注入到JavaScript文本的方法。但是它只支持最原始的几种数据类型,因此也局限了API设计。并且在Android 2.3模拟器上不稳定,在真机上也会遇到 issue #12987的问题。在IOS上更糟 UIWebView没有公共的APIs支持JavaScript到Objective-C的交互(你必须使用似有的APIs才能达到与addJavascriptInterface相同的功能)。

PhoneGap 是基于 UIWebView and WebView的比较出名的项目。开发者被迫使用回调函数从JavaScript APIs得到返回值。这在游戏上效率极低,也更为复杂。

早期的ngCore同样依赖UIWebView来支持iOS。但是这个机制由于其糟糕的表现被取代。

为了获得更好的表现、灵活性、兼容性,嵌入全功能的JavaScript引擎变得更为有效。