iOS JS 和 OC交互 / JS 和 native 相互调用

现在app 上越来越多需求是通过UIWebView 来展示html 或者 html5的内容, js 和 native OC代码交互 就非常常见了.

js 调用 native  OC代码

第一种机制

(1)最常用的是 利用 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 这个UIWebView 代理方法里拦截 JS 发送的请求,如果是约定的请求 那么就触发本地该执行的OC方法

我遇到常用的两种场景:

(1.1)页面缓冲加载过程中 该shouldStartLoadWithRequest:就可拦截多个请求,查找约定的关键字,锁定约定请求即可触发本地OC

(1.2)页面有按钮类别的焦点区域, 点击触发请求,通过 shouldStartLoadWithRequest: 对请求进行判断 ,触发本地OC

举例:html 分享按钮

<html>
    <header>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <script type="text/javascript">function shareClick() {
                loadURL("iOS//:shareAction");//这个链接对应 下面iOS方法中同一链接的关键字
            }
        </script>
    </header>

    <body>
        <h2> 点击webView上面的按钮 触发本地 OC 分享方法 </h2>
        <button type="button" onclick="shareClick()">按钮名称</button>
    </body>
</html>
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSString *requestUrl = request.URL.absoluteString;   DLog(@"请求URL:%@",requestUrl);   //判断是商品
  if(![NSString isEmpty:requestUrl] && [requestUrl hasPrefix:@"hfmall://"])
    {//约定 按请求前缀 是"hfmall://"来判断是商品 甚至可以从请求链接里面截取有效参数 如果频繁处理并且几个参数或者说有特殊字符,应该考虑用json进行64位编拼在链接上传过来
        NSRange range = [requestUrl rangeOfString:@"hfmall://"];
        if (range.length > 0) {
            NSString *shangpinId = [requestUrl substringFromIndex:range.length];
            GoodsDetailViewController *detailVC = [[GoodsDetailViewController alloc] init];
            detailVC.shangpin_id = shangpinId;
            [self.navigationController pushViewController:detailVC animated:YES];
            return NO; //执行本地代码 返回NO
        }
    }   //点击UIWebView页面上分享按钮 执行本地OC 分享方法   //是文章分享   NSRange range1 = [requestUrl rangeOfString:@"ios//:shareAction"];   if (range1.length != 0) {      [self share]; //执行分享方法      return NO;   }   //TODO:其他情况拦截判断   return YES;//无有效需要拦截的链接 走系统默认方法}

第二种机制

JavaScripCore

该框架 在 iOS7开始出现,可以实现 js 和 native OC原生交互,添加头文件#import <JavaScriptCore/JavaScriptCore.h>

[webView loadRequest:request];请求开始或者请求完成后获取js上下文

(1)js 自由选择时机调用native端 OC 代码

html端

<html>
    <header>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <script type="text/javascript">
            function secondClick() {
                iosHideBottomBar(‘参数1‘,‘参数2‘);//和 OC代码中标记红色背景关键名称一样 即可识别
            }        </script>
    </header>

    <body>
        <h2> js 自由选择时机调用native端 OC 代码 </h2>
        <button type="button" onclick="secondClick()">按钮名称</button>
    </body>
</html>
//获取js上下文JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

context[@"iosHideBottomBar"] = ^() { // @"iosHideBottomBar"为和js 约定执行的方法名,这样js 可以自由选择时机调用native端 OC 代码

DLog(@"%@",[NSThread currentThread]);//打印当前线程

     NSArray *args = [JSContext currentArguments];//回调js 方法iosHideBottomBar传递的参数

        for (JSValue *jsVal in args) {

            DLog(@"%@", jsVal.toString);

        }

__block JSContext *contextObject = context;

dispatch_async(dispatch_get_main_queue(), ^{

self.isShowLikeFooter = NO;

[self handleHiddenBottomBar];

NSString *[email protected]"xxxxx(‘如果需要传递返回值‘)"; //准备执行的js代码 按约定方法xxxxx回传返回值

[contextObject evaluateScript:jsString];

});

};

//该闭包是在非主线程中得到的回调,如果需要处理UI要在主线程更新 当前测试环境 为 XCode 8.0 模拟器 5s 8.3 打印结果如下

/**2016-11-11 17:05:54.447 dailylife[4163:181210] <NSThread: 0x7ff68cc2fd90>{number = 7, name = (null)}

(lldb) po [NSThread currentThread]

<NSThread: 0x7ff68a423150>{number = 1, name = main}

**/

小节:

两种机制不同:

a.  前者需要 不断对js 发起的每一条请求进行过滤判断,再执行早已定义好的OC方法,因为无法预知具体需要触发本地OC方法时机,

b.  后者 js 和 OC约定同一个方法名做识别关键字iosHideBottomBar 年 在JSContext获取webView js上下文,告诉js 本地有这个同样方法名的OC方法,你可以随时调用(子线程中).

体验下来,发现 后者这种 webView 控制调用更合理,在需要的时候调用.  但是现在好多第三方 用的都是前者,拦截url判断的方法,比如"有赞"就是,所以两种方法 我们都应该掌握,在需要的的时候选择相对更优的方式处理实现

native OC 调用 js

调用时机是应该是 webFinishLoad后,

(1)stringByEvaluatingJavaScriptFromString : 我常用这个方法去获取 webView标题

NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];

@"document.title" 传递给js  (js call native) 是异步的

当js 返回的 title字符串 (native call  js) 是同步得到的

stringByEvaluatingJavaScriptFromString 方法应该在主线程中执行,

这个方法也可以oc js相互传递参数

这个方法调用时机:应该在webview 请求完成后再调用 js 方法,这里才能用stringByEvaluatingJavaScriptFromString,因为

要等页面加载完,页面没加载完就相当于有些对象不一定创建成功,那么用js时候就容易找不到对象

(2)

//创建对象 context 获取 js上下文
JSContext *context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];      \NSString *jsString=@"iosHideBottomBar(‘参数1‘,‘参数2‘)"; //准备执行的js代码 并向iOS 传递参数1 参数2
[context evaluateScript:jsString];//通过oc方法调用js的 iosHideBottomBar

其他情况:

我还特意考虑了 相互需要返回值的可能

在具体上面方法举例,使用方法名时候 有特意强调参数,和返回值的情况不再赘述

参考:

http://blog.devtang.com/2012/03/24/talk-about-uiwebview-and-phonegap/

http://www.jianshu.com/p/d19689e0ed83

时间: 2024-08-26 03:00:53

iOS JS 和 OC交互 / JS 和 native 相互调用的相关文章

转载 【iOS开发】网页JS与OC交互(JavaScriptCore) OC -----&gt;JS

目标 本文介绍利用苹果在iOS7时发布的JavaScriptCore.framework框架进行js与OC的交互.我们想要达到的目标是: OC调用网页上的js方法 网页js调用APP中的OC方法 JavaSciptCore.framework框架介绍 JavaScriptCore是webkit的一个重要组成部分,主要是对js进行解析和提供执行环境.具体介绍请看这篇简书的文章:JavaScriptCore 使用 准备环境 创建一个名为JS与OC交互Demo的iOS工程.然后在storyboard添

史上最全的 UIWebview 的 JS 与 OC 交互

来源:伯乐在线 - 键盘风筝 链接:http://ios.jobbole.com/89330/ 点击 → 申请加入伯乐在线专栏作者 其实一直想给大家整理一下JS与OC的交互,但是没有合适的机会,今天借着微信小应用的发布,以及以后H5必定越来越流行,所以给大家整理一下. 交互方式有三种: 1.UIWebviewDelegate 2.JavaScriptCore 3.WebViewJavascriptBridge按照排序给大家介绍一下,我推荐前两种方法,第三种需要依赖第三方框架,并且不一定能拦截成功

Js与OC交互

Js与OC交互 源码请点击github地址下载. 下面讲述实现OC和JS的交互,它们相互调用,其中需要写一个静态的HTML文件用于提供JS方法. 效果图如下: screen.png 一.OC调用JS: 不说闲话,看代码如下 需要先在js文件定义方法postStr供oc调用 function postStr(string) { return 'I am the return parameter JS, and param ' + string; } oc代码只需一句即可调用 NSString *s

前端页面js与flash交互——js获取flash对象,并传递参数

背景介绍: 最近在搞一个项目,涉及到图片选取,裁剪,上传等,由于浏览器安全性问题,js无法获取到<input type="file">中选取的文件路径,而且对照片的裁剪,抠图等由HTML5实现的功能,对各大浏览器的兼容性,真是不敢太大胆.这个时候就引进了flash,然后所有js做不了的让flash来做,然后由js来控制页面元素.就这样开始了js与as的交互之旅,听做flash的大叔说,flash调js的函数式很好调的,而js调as不大容易.最终的情况是as调js错误层出不穷

UIWebView中JS与OC交互 WebViewJavascriptBridge的使用

一.综述 现在很多的应用都会在多种平台上发布,所以很多程序猿们都开始使用Hybrid App的设计模式.就是在app上嵌入网页,只要写一份网页代码,就可以跑在不同的系统上.在iOS中,app多是通过WebView来加载网页,由于功能需求等原因,代码中少不得要和跟网页交互. 二.原理 在iOS中,本地调用Javascript语言,是通过UIWebView中的实例方法stringByEvaluatingJavaScriptFromString:来实现的,该方法通过字符串对象的形式传入JS代码. [w

利用WKWebView实现js与OC交互注意事项

最近在写一些关于wkwebview的一些代码,发现了几点心得,记录一下. 1.js调用OC 我是利用wkwebview进行的开发实现,主要代码有三部分 1.向config注入OC对象 [config.userContentController addScriptMessageHandler:self name:@"YHModel" ]; 2.js中书写调用方法: window.webkit.messageHandlers.YHModel.postMessage({ height: $(

JS和OC交互的简单应用

先简单地说一下思路吧 需求:在App中嵌入一个webView,已经有了网址,但是需要去掉这个网页中的一些内容 解决方案:取到webView要加载的网址,对这个网址对应的网页信息进行修改 简单描述: 遵守webView的协议 <UIWebViewDelegate> 设置代理 实现相应代理方法,对网页信息中要删除的内容对应到节点,并删除 删除的部分处理:获取到相应的节点并执行删除操作的语句写法有三种方式:见http://www.w3school.com.cn/js/js_htmldom.asp 1

js中子页面父页面方法 变量相互调用

(1)子页面调用父页面的方法或者变量: window.parent.方法()或者变量名window.parent相当于定位到父页面  之后的操作和在父页面中写代码一样写 window.parent.aa();//调取aa函数 window.parent.bb;//调取bb变量 例如:想在子页面中得到id为aaa的文本框的值 window.parent.$("#aaa").val();//这种写法的前提是引用了jquery window.parent.getElementById(&qu

js中的js原生对象和jquery对象的相互调用

js中js原生对象是不能使用jquery对象的方法的,比如 jsobj.html()这样是调用不了的,同时$('jqobj').innerHTML 同样是错误的的 实例代码: $(function() { // console.log($('.contentdiscuss')[0].innerHTML.length) var lctobj={}; lctobj.lookmore=(function(){ var ct=$('.contentdiscuss'); for(var i=0;i<ct.