`
shappy1978
  • 浏览: 698524 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

[Trans] Integration between OC and JS

 
阅读更多

 

 

iOS 开发中,我们时不时的需要加载一些 Web 页面,一些需求使用 Web 页面来实现可以更可控,如上线后也可以发布更新,修改 UI 布局,或者修复 bug,这些 Web 页面的作用不止是展示,很大一部分是需要和原生代码实现的 UI 和业务逻辑发生交互的,那么不可避免的,就需要用一些方法来实现 Web 页面(主要是 JavaScript)和原生代码之间的通信,在 JavaScriptCore 出现之前,很多项目都在用 WebViewJavascriptBridge 作为 Web 页面和原生代码之间的一个桥梁(bridge),来传输一些数据和方法的调用,如 Facebook MessengerFacebook Paper 等。

WebViewJavascriptBridge 原理简述

WebViewJavascriptBridge 的原理是通过自定义 scheme,在加载一个特定标识的URL( wvjbscheme://__BRIDGE_LOADED__)时在 UIWebView 的代理方法 webView:shouldStartLoadWithRequest:navigationType: 中拦截 URL 并通过 UIWebView 的 stringByEvaluatingJavaScriptFromString: 方法执行一段 JS,这个 JS 文件中声明了一些变量和方法,在通讯中作为一个桥梁,那么怎么通讯呢?

JS 中调用 OC 的方法

在 OC 中,实例化一个 WebViewJavascriptBridge 并调用 registerHandler:handler: 注册并监听一下事件,第一个参数是一个字符串,用来标识一个特定的事件,handler 是一个 block,方法内部将标识作为 keyhandler 作为值保存。

- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler {
    _base.messageHandlers[handlerName] = [handler copy];
}

当 JS 中需要调用 OC 的方法时,组装一个类似结构的数据,一个字符串作为标识,将需要传输的数据作为值并保存在一个全局数组中

var sendMessageQueue = [];
function _doSend(message, responseCallback) {
        if (responseCallback) {
            var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime();
            responseCallbacks[callbackId] = responseCallback;
            message['callbackId'] = callbackId;
        }
        // 主要就是这一行,将 message 保存到全局数组,供待会儿查询
        sendMessageQueue.push(message);
        messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE;
}

并触发一个特定的 URL(wvjbscheme://__WVJB_QUEUE_MESSAGE__),UIWebView 则在 webView:shouldStartLoadWithRequest:navigationType: 中拦截这个 URL,并执行一段 JS(WebViewJavascriptBridge._fetchQueue();

function _fetchQueue() {
    var messageQueueString = JSON.stringify(sendMessageQueue);
    sendMessageQueue = [];
    return messageQueueString;
}

查询 JS 中全局数组中的值,并转成 JSON 字符串返回,OC 中拿到 JSON 字符串,并解析,得到一个数组,遍历数组,根据数组中每个对象的 handlerName 查询 OC 中是否有注册这个事件,如果有注册,则根据 handlerName 取出保存在字典中的 block,并执行这个 block,block 可以接收一个 id 类型的参数,将 JS 全局数组中根据 handlerName 取出来的数据作为参数传入 block。这样就实现了从 JS 到 OC 中的数据传输。

OC 中调用 JS 的方法

OC 中调用 JS 的方法相对简单,因为 UIWebView 可以主动执行 JS,JS 中可以将需要监听的事件注册,同样是字符串作为标识,一个函数作为值,保存到一个全局对象中,在 OC 中主动执行特定的 JS 方法时,将数据封装成 JSON 字符串,传入标识符和数据,并遍历 JS 中保存 handler 的全局对象,看有没有注册相应的事件,如果有,根据 事件的名字得到一个函数并执行。实现了 OC 调用 JS 中的方法并向 JS 中传输数据。

JavaScriptCore 时代的通讯

iOS 7 开始,苹果提供了一个叫作 JavaScriptCore 的框架,使用 JavaScriptCore 框架可以实现 OC 和 JS 的互相调用,而不需要依赖「桥」来实现,怎么通讯呢?

JavaScriptCore 中 OC 调用 JS 方法

在 JS 中定义一个方法

  function alertFunc() {
    window.alert("这是一个JS中的弹框!")
  }

在 webViewDidFinishLoad: 代理方法中,获取到 JSContext 对象

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    
    [context setExceptionHandler:^(JSContext *ctx, JSValue *expectValue) {
        NSLog(@"%@", expectValue);
    }];
    
    self.context = context;
}

在一个 button 的点击事件中可以根据 JS 定义的方法的名字获得一个 JSValue 类型对象,这个对象就是在 JS 中定义的方法,JSValue 对象通过调用 callWithArguments: 方法,执行这个 JS 方法。

- (IBAction)buttonClick:(UIButton *)sender {
    if (!self.context) {
        return;
    }
    
    JSValue *funcValue = self.context[@"alertFunc"];
    [funcValue callWithArguments:nil];
}

点击按钮时,效果如下。

实现了 OC 中调用 JS 的方法。

JS 调用 OC 中的方法

在 OC 中,通过给 JSContext 的一个 key 赋值,值为一个 block,key 是 JS 中调用的方法的名字,代码如下:

    self.context[@"ocAlert"] = ^{
        // block 异步执行,如果涉及到 UI 的操作需要回到主线程操作
        dispatch_async(dispatch_get_main_queue(), ^{
            __strong typeof(weakSelf) strongSelf = weakSelf;
            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:@"这是OC中的弹框!" preferredStyle:UIAlertControllerStyleAlert];
            [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                [alert dismissViewControllerAnimated:YES completion:^{
                    
                }];
            }]];
            [strongSelf.navigationController presentViewController:alert animated:YES completion:nil];
        });
    };

在 Web 页面中创建一个 button 并设置 button 的 onClick 事件调用 ocAlert 方法

点击这里

点击 Web 页面上的 button 按钮,效果如下

实现了 JS 调用 OC 中的方法。

是不是方便了很多?

写在后面

嗯 ,一篇文章应该有个写在后面的。

以上当然只是 JavaScriptCore 框架的一个很小的应用,使用 JavaSciptCore 框架结合 Objective-C 的动态性可以做很多事,比如著名的热修复框架 JSPatch 就是这两者的结合。这里只是演示了 JS 和 OC 之间的方法调用,并没有传输数据,JavaScriptCore 框架是很容易的实现两者之间的数据传输的。具体做法可以参考参考资料。

苹果添加的这些新特性可以给开发带来很多便利,就是不知道有坑没有,嗯,且爬且珍惜吧。

使用 JavaScriptCore 进制通讯的 demo 放到了 GitHub,地址如下:
https://github.com/cielpy/CPYJSCoreDemo

参考资料

分享到:
评论

相关推荐

    Titles for ieee trans journal

    IEEE TRANSACTIONS ON AEROSPACE AND ELECTRONIC SYSTEMS AES IEEE Trans. Aerosp. Electron. Syst. ANE* IEEE Trans. Aeronaut. Navig. Electron.* ANE* IEEE Trans. Aerosp. Navig. Electron.* AS* IEEE Trans. ...

    TransMac11.4免安装版

    TransMac是一款专为Windows用户设计的软件,它允许用户轻松地与Apple的Mac OS系统进行交互,特别是处理与Mac相关的文件格式和磁盘操作。在标题"TransMac11.4免安装版"中,我们可以理解这个版本是11.4的TransMac,...

    TransMac 12.3.rar

    TransMac是一款专为Windows用户设计的软件,它允许用户方便地与Apple的Mac OS文件系统进行交互,包括读取、写入以及管理Mac格式化的磁盘和存储设备,如HFS、HFS+、APFS等。这个压缩包“TransMac 12.3.rar”包含了...

    TransMac v8.1

    TransMac is a Windows program that can copy files to and from Macintosh disks. It supports most disk types, including high density diskettes, CD-ROM, hard drives, IEEE 1394 (FireWire), USB and most ...

    TransE算法代码实现.rar

    TransE算法是知识图谱表示学习领域的一种经典方法,它由Nicolas Usunier等人在2013年提出。该算法的主要目的是将实体和关系映射到一个低维向量空间,使得在这个空间中,关系可以被视为实体之间的翻译操作。这种直观...

    IEEE Trans系列期刊论文投稿模板

    提供的"Transactions-template-and-instructions-on-how-to-create-your-article-formatted.docx"文件是一个完整的论文word模板,设计符合IEEE Transactions的标准格式。你可以直接将你的研究内容插入到这个模板中...

    TransMac_14.4

    《TransMac 14.4:Mac OS 镜像刻录的专业利器》 在数字化时代,数据存储和传输的方式多种多样,其中一种常见的格式就是Mac OS的.dmg镜像文件。这种文件类型广泛用于软件分发、系统备份以及跨平台的数据交换。然而,...

    TransMac.v10.4 好用的黑苹果软件

    "TransMac.v10.4 好用的黑苹果软件" 这个标题指出了我们讨论的核心是一款名为 TransMac 的软件,其版本号为 10.4。它被形容为“好用的黑苹果软件”,这暗示了TransMac是一款专门针对在非苹果(即Windows系统)环境下...

    TranSE算法实现及测试

    《 TranSE算法实现及测试详解 》 在知识图谱的研究与应用中,实体关系的表示学习是一项核心任务。TranSE(Translation-based Knowledge Graph Embedding)算法是其中的一种经典模型,它通过向量空间中的翻译操作来...

    IEEE FORMAT AND TRANS

    在IT行业中,IEEE(Institute of Electrical and Electronics Engineers)是一个全球知名的工程技术专业组织,它制定了许多技术标准,尤其是在电子、电气、计算机工程等领域。其中,IEEE格式是学术论文撰写的标准...

    transmac 10.3 注册版

    transmac 10.3 注册版,在Win下访问Mac分区并操作的软件 高于这个版本的找不到序列号

    transMac.zip

    《transMac:跨越平台的苹果系统管理利器》 在IT领域,尤其是在苹果用户群体中,transMac是一款不可或缺的工具,它允许Windows用户轻松地管理和处理Mac格式的硬盘、USB驱动器以及DMG映像文件。"transMac.zip"这个...

    trans-formas仪表操作

    "Trans-Formas"仪表操作涉及的是一个可能与数据转换、数据分析或监控系统相关的工具或技术。在IT行业中,仪表通常指的是用户界面中用于显示实时数据、指标或性能的图形化组件,它们常用于监控系统状态、业务表现或...

    IEEEtrans论文的latex模板

    模板的关键词“最新”意味着它包含了最新的格式和规范要求,能够帮助作者符合TIP(IEEE Transactions on Image Processing)和TPAMI(IEEE Transactions on Pattern Analysis and Machine Intelligence)等知名期刊...

    TransMac12.2破解版

    TransMAC12.2是一个在Windows下写入苹果镜像的软件,一般用于将原版MacOS原版镜像烧录到U盘,安装黑苹果必备,这个最新的12.2破解版,解压后替换主文件即可完成破解

    TransMac11破解版

    TransMac11破解版 黑苹果安装专用 小白们来下载

    TransMac.11.0内附注册

    TransMac.11.0内附注册,在windows下制作mac的启动盘

    黑苹果系统U盘制作工具TransMac121.zip

    标题中的“黑苹果系统U盘制作工具TransMac121.zip”指的是用于在Windows操作系统上创建启动用USB驱动器的工具,特别适用于安装苹果的 macOS(通常被称为“黑苹果”系统,即非官方的苹果系统在非苹果硬件上运行)。...

    TransMac.zip

    TransMac是一款专为Windows用户设计的软件,用于方便地读取、写入及管理Macintosh格式的硬盘和光盘。这个工具在“黑苹果”(Hackintosh)领域中尤其重要,因为很多Windows用户想要访问或操作苹果Mac OS系统格式化的...

    TransMac12.1以及破解补丁

    先安装好TransMac,再把破解补丁解压到任意路径,运行后确认安装路径,点击Activate激活。激活后不要更新软件。

Global site tag (gtag.js) - Google Analytics