UIWebView 中JavaScript 与 Objective-C 通信

深入解析 Android 的 evaluateJavascript 在 Android 应用开发中,WebView是一个常用组件,用于嵌入 Web 页面。然而,除了简单地加载和展示网页内容,应用常常需要与 Web 页面中的 JavaScript 进行交互。这时,Android 提供了 evaluateJavascript方法,允许开发者在WebView中执行 JavaScript 代码,并通过回调获取执行结果。在这篇文章中,我们将详细介绍 webView.evaluateJavascript方法的使用场景及其优势,并探讨与之配合使用的 ValueCallback。 阅读详情


iOS7 之前

Objective-C -> JavaScript

UIWebView对象有以下方法

 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script

该方法能够执行一段JavaScript字符串, 并返回字符串类型的返回值. 例如:

UIWebView *webView = [[UIWebView alloc] init];

// result ==  @"3"
NSString *result = [webView stringByEvaluatingJavaScriptFromString:@"1+2"];

// 调用js 对象的方法
NSString *result2 = [webView stringByEvaluatingJavaScriptFromString:
                        @"window.objectApis.doSomething('hello')"];
缺点

以上方法有以下缺点:

  1. 返回值类型只能是字符串类型
    • Objective-C 需要对字符串结果进行反序列化
    • JavaScript 可能需要对结果进行序列化
  2. 调用JavaScript对象的方法时, 传入参数比较麻烦
    • Objective-C 需要对参数进行序列化
    • JavaScript 可能需要对字符串参数进行反序列化
// 调用js 对象的方法
NSString *result2 = [webView stringByEvaluatingJavaScriptFromString:
                        @"window.objectApis.doSomething('hello \" world')"];

JavaScript -> Objective-C

URL请求截获

在UIWebView的浏览器的JavaScript中, 没有相关的接口可以调用Objective-C的相 关方法. 一般采用JavaScript 在浏览器环境中发出URL请求, Objective-C 截获请 求以获取相关请求的思路. 在Objective-C 中在实现UIWebViewDelegate 时截获请求:


- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
                                                 navigationType:(UIWebViewNavigationType)navigationType
{

    NSString *url = request.URL;
    // if (url是自定义的JavaScript通信协议) {
        //
        // do something
        //
        // 返回 NO 以阻止 `URL` 的加载或者跳转
        // return NO;
    // }
}

Objective-C可以在webView:shouldStartLoadWithRequest:navigationType 方法中可以返回NO 以阻止URL的加载或者跳转.

JavaScript有各种不同的方式发出URL 请求:

  • location.href : 修改window.location.href 替换成一个合成的URL, 比如 async://method:args
  • location.hash : 修改 window.location.hash
  • <a> click : 创建一个<a> 元素, 赋值href 属性, 并调用其click() 方法
  • iframe.src : 创建一个iframe 元素, 赋值src 属性
  • XHR sync/async : 创建一个XMLHttpRequest 对象, open() 中设置相关信息及是否异步, 并调用send() 方法发出请求
var linkNode = document.createElement("a");
var pongUrl;
var xhr = new XMLHttpRequest();
var iframe = document.createElement("iframe");
iframe.style.display = "none";

function ping(mechanism, startTime) {
    pongUrl = "pong://" + startTime;
    switch (mechanism) {
        // location.href
        case Mechanism.LocationHref:
            location.href = pongUrl;
            break;
        // location.hash
        case Mechanism.LocationHash:
            location.hash = "#" + pongUrl;
            break;
        // <a> click
        case Mechanism.LinkClick:
            linkNode.href = pongUrl;
            linkNode.click();
            break;
        // iframe. src
        case Mechanism.FrameSrc:
            iframe.src = pongUrl;
            document.body.appendChild(iframe);
            document.body.removeChild(iframe);
            break;
        // XHR sync/async
        case Mechanism.XhrSync:
        case Mechanism.XhrAsync:
            xhr.open("GET", pongUrl, mechanism == Mechanism.XhrAsync);
            xhr.send();
            break;
    }
}

在UIWebView 中, Objective-C 可以通过NSHTTPCookieManagerCookiesChangedNotification 事件以监听cookie的变化.

NSNotificationCenter *center = NSNotificationCenter.defaultCenter;
[defaultCenter addObserverForName:NSHTTPCookieManagerCookiesChangedNotification
                           object:nil
                            queue:nil
                       usingBlock:^(NSNotification *notification) {
                           NSHTTPCookieStorage *cookieStorage = notification.object;
                           // do something with cookieStorage
                       }];

当JavaScript 修改 document.cookie 后, Objective-C 可以通过分析cookie以得到信息.

缺点

无论是URL请求截获方式还是监听Cookie的方式, 都有以下缺点:

  1. 整个过程是异步的, 不能同步
  2. 在JavaScript中不能直接获取Objective-C处理的返回值
    • 需要Objective-C 调用JavaScript层自己实现的api才能得到返回值
  3. 使用callback 比较麻烦
    • 需要在JavaScript 上自己实现

iOS 7+

iOS7 引入了JavaScriptCore, 是的JavaScript 和 Objective-C 可以互操作.

Objective-C 可以使用JSContext 的 evalueScript() 方法调用JavaScript 提供 的方法.

#import <JavaScriptCore/JavaScriptCore.h>

...

UIWebView *webView = [[UIWebView alloc] init];
JSContext *jsContext = [webView valueForPath: @"documentView.webView.mainFrame.javaScriptContext"];

// call javascript
[jsContext evalueScript: @"window.objectApis.doSomething()"];

将实现JSExport 协议的对象直接赋值给JSContext 对象的属性即可暴露方法给JavaScript.


// provide obj-c apis
WBNativeApis *nativeApis = [[WBNativeApis alloc] init];
jsContext[@"nativeApis"] = nativeApis;

// `WBNativeApis` Class

#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h>

@protocol NativeApis <JSExport>

-(void) logMessage: (NSString *) message;
-(NSString *) version;
// 异步
-(void) asyncPrint: (NSString *) message;
// callback
-(void) asyncPrint: (NSString *) message callback: (JSValue *) callback;

@end

@interface WBNativeApis : NSObject <NativeApis>
@end

在浏览器环境中使用JavaScript 调用Objective-C 的api

window.nativeApis.logMessage('A message from javascript!');
window.asyncPrintCallback('Message from javascript!', function (data) {
    var div = document.createElement('div');
    div.innerText = "Send message to native ok and get data from native";
    document.body.appendChild(div);
});

JavaScriptCore 将各种类型数据在不同编程语言间做了转换, 可进行直接操作.

   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)

性能测试

在iPhone 5S (ios 7.1) 模拟器条件下测试各种通信方式一次通信花费的毫秒(ms)时间.

MethodAvgMinMax
location.href1.440.7013.59
location.hash1.000.666.19
<a> click1.400.6615.29
iframe.src1.471.055.41
XHR sync1.360.853.44
XHR async0.850.4614.96
document.cookie0.420.211.59
JavaScriptCore0.060.040.13

从表格中可以看出, JavaScriptCore 的通信方式性能最好.

兼容性

各种通信方式的兼容性如下( + 表示支持, X 表示不支持):

Method/DeviceiOS4iOS5iOS6iOS7iOS8
location.href+++++
location.hash+++++
<a> click+++++
iframe.src+++++
XHR sync+X+++
XHR async+X+++
document.cookie++++X
JavaScriptCoreXXX++

WKWebView (iOS 8 + )

iOS 8 引入WKWebView, WKWebView 不支持JavaScriptCore的方式但提供message handler的方式为JavaScript 与Objective-C 通信.

在Objective-C 中使用WKWebView的以下方法调用JavaScript:

- (void)evaluateJavaScript:(NSString *)javaScriptString
         completionHandler:(void (^)(id, NSError *))completionHandler

如果JavaScript 代码出错, 可以在completionHandler 进行处理.

在Objective-C 中注册 message handler:

// WKScriptMessageHandler protocol


- (void)userContentController:(WKUserContentController *)userContentController
    didReceiveScriptMessage:(WKScriptMessage *)message
{
    NSLog(@"Message: %@", message.body);
}

[userContentController addScriptMessageHandler:handler name:@"myName"];

在JavaScript 将信息发给Objective-C:

// window.webkit.messageHandlers.<name>.postMessage();


function postMyMessage()
 {

    var message = { 'message' : 'Hello, World!', 'numbers' : [ 1, 2, 3 ] };

    window.webkit.messageHandlers.myName.postMessage(message);

}

参考资料

  1. http://blog.persistent.info/2013/10/a-faster-uiwebview-communication.html
  2. https://github.com/mihaip/web-experiments/pull/1
  3. http://www.bignerdranch.com/blog/javascriptcore-example/
  4. http://oscaraperez.com/blog_assets/JavaScript%20with%20iOS7.pdf
  5. http://blog.impathic.com/post/64171814244/true-javascript-uiwebview-integration-in-ios7
Matlab实现Transformer-BiLSTM多变量时间序列预测与GUI设计 时间序列预测是工业与科研场景中的核心需求,尤其在多变量环境下,如何从历史数据中捕捉局部动态与长期依赖成为建模难点。循环神经网络擅长记忆短期时序模式,而注意力机制能建模全局关联,两者结合可互补不足。本文基于Matlab平台,系统讲解Transformer-BiLSTM混合模型在多输入多输出预测任务中的实现全流程,包括滑窗构造样本、特征归一化、网络维度对齐、训练策略及App Designer界面设计,并分享训练过程中的典型踩坑与调参经验。该方案适用于负荷预测、设备状态估计等多传感器融合场景,为工程落地提供了一套 阅读详情

相关推荐

【Python爬虫案例教学】超简洁代码采集原神所有角色信息

(。・∀・)ノ゙嗨 大家好,这里是池鱼

xiaoyuan_____的博客 2421

iOS中Objective-C与JavaScript之间相互调用的实现(实现了与Android相同的机制)

最近在iOS项目中需要使用到oc与js之间的相互调用,而且要求是实现方式必须与Android中的相同,方便js中统一处理。于是在对第三方库WebViewJavascriptBridge进行研究之后,仿照Android中的WebView与JS的交互机制,实现了一个,在这里分享给大家。 首先要说明的是,在iOS中js调用Objective-C的代码只能通过重定向的形式进行,即js中通过修改ifram

心砚THU的专栏 1万+

沐数科技数据开发岗笔试题2025

与数据库中的主键(Primary Key)​有所不同,业务主键(Business Key)​是业务层面的唯一标识,通常由业务规则决定,例如,订单号、订单明细号,身份证号等。用户授信表(table_credit):包含用户ID(uid)、授信申请时间(credit_submit_time_local)、授信状态(credit_status)。:在正态分布中,大约68%的数据值落在距离均值一个标准差的范围内,约95%的数据值落在两个标准差的范围内,而约99.7%的数据值落在三个标准差的范围内。

weixin_40121264的博客 3525

iOS开发之Objective-C与JavaScript的交互

UIWebView是iOS最常用的SDK之一,它有一个stringByEvaluatingJavaScriptFromString方法可以将javascript嵌入页面中,通过这个方法我们可以在iOS中与UIWebView中的网页元素交互。 stringByEvaluatingJavaScriptFromString    使用stringByEvaluatingJavaScriptF

dean19900504的专栏 781

海康威视工业相机SDK二次开发实战:多相机同步采集与图像存储

本文详细介绍了海康威视工业相机SDK二次开发实战,包括多相机同步采集与图像存储的优化方案。通过MVS软件搭建开发环境,实现硬件与软件触发同步采集,并提供高效的图像存储管理技巧,帮助开发者提升工业视觉项目的效率与稳定性。

weixin_29168813的博客 666

vue 插件vue-awesome-swiper实现 三张图片,左右两边显示一半的效果的示例

希望我的愚见能够帮助你哦~,若有不足之处,还望指出,你们有更好的解决方法,欢迎大家在评论区下方留言支持,大家一起相互学习参考呀~

weixin_50450473的博客 3249

Android 网页交互详解和mWebview.evaluateJavascript带参数注意事项

android 4.4以下跟H5交互需要调用webview的loadUrl(javascript:方法名(参数))来实现调用js方法。如果需要网页获取返回值还需要网页调用安卓 @JavaScriptInterface 注解的方法才可以。 Android 4.4以上调用webview.evaluateJavascript(javascript:方法名(参数),new ValueCallback{...

u011339364的专栏 2万+

5-->详解《switch 数据接收驱动框架、mtk7621集成交换芯片mt7530》之一

SWITCH 交换芯片驱动配置: 一、 配置 MDIO 总线 二、配置 MAC 接口 三、基于 MAC 的 DMA 配置 四、设备驱动结构体 五、数据收发包

weixin_38387929的博客 1万+

android通过WebView的evaluateJavascript()调用JS

因为该方法的执行不会使页面刷新,而方法(loadUrl )的执行则会使页面刷新。 Android 4.4 后才可使用 同:https://www.cnblogs.com/liuyj-vv/p/9583831.html 仅java代码不同,可以接收JS函数的返回值 public class MainActivity extends Activity { ...

weixin_30797027的博客 2979

深度强化学习训练结果曲线绘制教程

使用python语言,只调用matplotlib库,绘制训练过程中保存的强化学习训练曲线。模仿经典论文中的训练曲线,多次训练取平均,并绘制出阴影区域。

加斯顿工程师的博客 911

SAP 调用Ftp服务器

FTP(File transfer protocol)是一种标准的网络协议,可以用于在互联网上传递文件。SAP系统中可通过系列配置和提供的些标准函数,用于查看、更新、下载FTP服务器上的文件。提示:以下是本篇文章正文内容,下面案例可供参考。

qq_38304013的博客 1418

UIWebView 中 JS 与 Objective-C 通信

JavaScript -> Objective-C URL请求截获 在UIWebView的浏览器的JavaScript中, 没有相关的接口可以调用Objective-C的相 关方法. 一般采用JavaScript 在浏览器环境中发出URL请求, Objective-C 截获请 求以获取相关请求的思路. 在Objective-C 中在实现UIWebViewDelegate 时截获请求:

MGY_my的博客 831

更改训练好的yolo模型中的class类名,无需重新训练

本文介绍了如何在不重新训练YOLO模型的情况下修改其类名的技巧。关键点在于理解YOLO类名存储逻辑:类名列表(names)存储在配置文件中(.yaml),而非权重文件(.pt)。通过修改配置文件的类名列表(保持类别数量nc不变),即可实现类名更新。具体步骤包括:1)准备修改后的配置文件;2)加载模型并更新类名;3)验证推理结果。该方法适用于YOLOv5/YOLOv8等版本,能有效节省开发时间,适用于类名表述调整、多场景复用等需求。注意:增减类别需重新训练,仅修改类名时需确保类别数量一致。

yolo模型训练找我,AI游戏合作找我 881

UIWebView中Objective C和JavaScript通信

JS和OC的交互,使用到JavaScriptCore这个框架,用到的类和协议有JSExport 、JSContext 网页很简单,只有一个button按钮,button按钮的事件点击主要执行了wst.duobao('123');,wst是自定义的一个普通JS对象,在OC中需要使用到wst捕获对应的js方法调用。 网页html代码如下: <!DOCTYPE html> <html ...

weixin_34050427的博客 132

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

UIWebView中Objective-C和JavaScript通信

JS和OC的交互,使用到JavaScriptCore这个框架,用到的类和协议有JSExport 、JSContext 网页很简单,只有一个button按钮,button按钮的事件点击主要执行了wst.duobao('123');,wst是自定义的一个普通JS对象,在OC中需要使用到wst捕获对应的js方法调用。 网页html代码如下: html5page-oc

Aron1992的专栏 290

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

uiwebview与objective-c

本文转载至 http://blog.youkuaiyun.com/jaywon/article/details/7019828   利用oc调用js很简单, 系统直接提供了方法stringByEvaluatingJavaScriptFromString   [cpp] view plaincopy [webView stringByEvaluatingJavaSc...

weixin_34115824的博客 75

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

iOS中js与objective-c的交互(转)

因为在iOS中没有WebKit.Framework这个库的,所以也就没有 windowScriptObject对象方法了。要是有这个的方法的话 就方便多了,(ps:MacOS中有貌似) 现在我们利用其他方法去达到js与objective-c的交互效果。 首先是objective-c调用js中的代码,可以用uiwebview中的一个方法 stringByEvaluatingJavaScrip...

weixin_34174105的博客 159

UIWebView 获取当前的javascript上下文,并js,oc互调

OC调用UIWebView 中的js,网上例子很多,最常用的是UIWebView自带的一个方法; - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script; UIWebView中的js 掉用本地的oc方法; 通过UIWebView开始加载请求的代理方法中,去解析OC跟js约定好的协议(比如...

anxing1070的博客 180

如何快速实现iOS/OSX应用中的JavaScript与原生通信:WebViewJavascriptBridge完整指南

WebViewJavascriptBridge是一款强大的iOS/OSX通信桥接工具,专门用于在UIWebViews/WebViews中实现Objective-C与JavaScript之间的高效消息传递。本文将为初学者提供简单易懂的使用指南,帮助你快速掌握这一实用工具。 ## 📱 什么是WebViewJavascriptBridge? WebViewJavascriptBridge是一个轻量

gitblog_00918的博客 973

js(javascript)与OC(Objective-C)交互

实质上oc与js的通信交互就是发送消息,也即函数调用,iOS7以后官方公布JavaScriptCore framework中很方便我们对他们之间的相互调用。在以前我们只能通过UIWebView的UIWebViewDelegate协议来实现. 1 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest...

weixin_33928467的博客 127

OC 和 js 交互

首先导入 #import <JavaScriptCore/JavaScriptCore.h> 声明 对象 @property (nonatomic, strong) JSContext *context; 1, oc调用js的方法并获取参数 - (void)webViewDidFinishLoad:(UIWebView *)webView{...

dianpaiqiao0548的博客 132

UIWebView Objective C 和JavaScript 那点事

首先,以下再次纯属胡扯。     1、既然是javascript肯定离开不了webview(如果您自己写过类似V8引擎的牛叉玩意,请当我放屁),在iOS里面这玩意叫做UIWebView,有个delegate叫做:   UIWebViewDelegate。   2、首先webView会加载html页面,和javaScript到 webView的上下文中。   3、如果OC想操作

u010850094的博客 257

JS 与 iOS 交互

UIWebView 与 JS 交互 Swift 与 JS 交互: http://mp.weixin.qq.com/s?__biz=MzIzMzA4NjA5Mw==&mid=214070747&idx=1&sn=57b45fa293d0500365d9a0a4ff74a4e1#rdOC与JS 交互: http://mp.weixin.qq.com/s?__biz=MzIzMzA4NjA5Mw==

Emperor_huanzi 的博客 478

Object_C 与JavaScript交互使用总结

iOS开发中oc与js交互的方式有很多,我们可以使用流行的第三方库如:WebviewJavaScriptBridge和OVGap,这两个库都是让webview与JS建立起一条桥梁,我们也可以使用iOS原生的交互方式如:stringByEvaluatingJavaScriptFromString方法以及原生框架JavaScriptCore的使用。今天我们主要来讲解原生的方法使用,废...

weixin_30299709的博客 130

iOS端执行包含外部引用的js并相互通信

背景某些情况下,需要调用js的一些代码来执行一些操作,并且将处理结果回传到OC。概述为了执行一段包含外部引用的js,需要使用UIWebView,通过fileURL去加载一个js或者HTML页面,为了方便的在两个语言之间通信,需要借助一个第三方框架WebViewJavascriptBridge,它可以实现跨语言的请求与回调。实现本文讨论的是,从OC调用WebView加载的js的某个方法来处理数据,并且

最美的时光 1846
上一篇: Base64图片与UIImage的相互转化
下一篇: Vim 配色(color scheme)与随机配色
FuDesign2008
博客等级 码龄18年 44粉丝 119原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值