使用 JavaScriptCore 进行跨语言调用

news2024/10/6 2:53:57

使用 JavaScriptCore 进行跨语言调用时,既可以在 Native 代码中执行 JavaScript 代码,也可以在 JavaScript 中调用 Native 方法。以下是详细的实现步骤和示例。

1. 在 Native 代码中执行 JavaScript 代码

使用 JavaScriptCore 框架,可以在 Swift 或 Objective-C 代码中执行 JavaScript 代码,并获取执行结果。

示例(Swift)

步骤 1: 导入 JavaScriptCore 框架

import JavaScriptCore

步骤 2: 创建 JSContext 对象

let jsContext = JSContext()

步骤 3: 执行 JavaScript 代码

jsContext?.evaluateScript("var a = 2 + 2")
if let result = jsContext?.evaluateScript("a") {
    print("Result: \(result.toInt32())") // 输出: Result: 4
}

示例代码

import JavaScriptCore

class ViewController: UIViewController {
    var jsContext: JSContext!

    override func viewDidLoad() {
        super.viewDidLoad()

        jsContext = JSContext()

        // 在 JavaScript 中定义一个函数
        jsContext.evaluateScript("""
        function add(a, b) {
            return a + b;
        }
        """)

        // 在 Swift 中调用 JavaScript 函数
        if let addFunction = jsContext.objectForKeyedSubscript("add") {
            let result = addFunction.call(withArguments: [3, 4])
            print("Result of add function: \(result?.toInt32() ?? 0)") // 输出: Result of add function: 7
        }
    }
}

2. 在 JavaScript 中调用 Native 方法

通过 JavaScriptCore,可以将 Native 方法暴露给 JavaScript,这样就可以在 JavaScript 中调用这些方法。

示例(Swift)

步骤 1: 定义 Native 方法

let logFunction: @convention(block) (String) -> Void = { message in
    print("Log from JavaScript: \(message)")
}

步骤 2: 将 Native 方法添加到 JSContext

jsContext.setObject(logFunction, forKeyedSubscript: "log" as NSString)

步骤 3: 在 JavaScript 中调用 Native 方法

jsContext.evaluateScript("""
log('Hello from JavaScript');
""")

示例代码

import JavaScriptCore

class ViewController: UIViewController {
    var jsContext: JSContext!

    override func viewDidLoad() {
        super.viewDidLoad()

        jsContext = JSContext()

        // 定义一个 Native 方法
        let logFunction: @convention(block) (String) -> Void = { message in
            print("Log from JavaScript: \(message)")
        }
        jsContext.setObject(logFunction, forKeyedSubscript: "log" as NSString)

        // 在 JavaScript 中调用 Native 方法
        jsContext.evaluateScript("""
        log('Hello from JavaScript');
        """)
    }
}

3. 完整示例:双向调用

完整代码示例

import JavaScriptCore

class ViewController: UIViewController {
    var jsContext: JSContext!

    override func viewDidLoad() {
        super.viewDidLoad()

        jsContext = JSContext()

        // 定义一个 Native 方法
        let logFunction: @convention(block) (String) -> Void = { message in
            print("Log from JavaScript: \(message)")
        }
        jsContext.setObject(logFunction, forKeyedSubscript: "log" as NSString)

        // 在 JavaScript 中定义一个函数
        jsContext.evaluateScript("""
        function add(a, b) {
            log('Adding ' + a + ' and ' + b);
            return a + b;
        }
        """)

        // 在 Swift 中调用 JavaScript 函数
        if let addFunction = jsContext.objectForKeyedSubscript("add") {
            let result = addFunction.call(withArguments: [3, 4])
            print("Result of add function: \(result?.toInt32() ?? 0)") // 输出: Result of add function: 7
        }

        // 在 JavaScript 中调用 Native 方法
        jsContext.evaluateScript("""
        log('Hello from JavaScript');
        """)
    }
}

小结

通过 JavaScriptCore,可以在 Native 代码中执行 JavaScript 代码,并在 JavaScript 中调用 Native 方法,实现跨语言调用。这种双向通信机制使得混合应用程序可以充分利用 JavaScript 和 Native 各自的优势,提升应用的功能性和用户体验。


异步还是同步 ?这是一个问题

使用 JavaScriptCore 进行跨语言调用(在 Native 代码中直接执行 JavaScript 代码,在 JavaScript 中调用 Native 方法),是异步还是同步的 ?

使用 JavaScriptCore 进行跨语言调用时,通常情况下调用是同步的。这意味着在 Native 代码中直接执行 JavaScript 代码时,调用会阻塞直到 JavaScript 代码执行完成,并且可以立即获取结果。同样地,在 JavaScript 中调用 Native 方法时,也是同步执行的。

详细解释

Native 代码中执行 JavaScript 代码

在 iOS 的 Swift/Objective-C 代码中,可以通过 JSContext 来执行 JavaScript 代码。调用 JSContext.evaluateScript 方法时,代码会同步执行,并且在执行完成后立即返回结果。

示例代码

import JavaScriptCore

class ViewController: UIViewController {
    var jsContext: JSContext!

    override func viewDidLoad() {
        super.viewDidLoad()

        jsContext = JSContext()

        // 在 JavaScript 中定义一个函数
        jsContext.evaluateScript("""
        function add(a, b) {
            return a + b;
        }
        """)

        // 在 Swift 中调用 JavaScript 函数
        if let addFunction = jsContext.objectForKeyedSubscript("add") {
            let result = addFunction.call(withArguments: [3, 4])
            print("Result of add function: \(result?.toInt32() ?? 0)")
        }
    }
}

在这个示例中,evaluateScriptcall 方法都是同步的,执行 JavaScript 代码后立即返回结果。

JavaScript 中调用 Native 方法

通过 JavaScriptCore,可以在 JavaScript 中调用通过 JSContext 暴露的 Native 方法。这些调用同样是同步的,JavaScript 代码会等待 Native 方法执行完成,并获取结果。

示例代码

import JavaScriptCore

class ViewController: UIViewController {
    var jsContext: JSContext!

    override func viewDidLoad() {
        super.viewDidLoad()

        jsContext = JSContext()

        // 定义一个 Native 方法
        let logFunction: @convention(block) (String) -> Void = { message in
            print("Log from JavaScript: \(message)")
        }
        jsContext.setObject(logFunction, forKeyedSubscript: "log" as NSString)

        // 在 JavaScript 中调用 Native 方法
        jsContext.evaluateScript("""
        log('Hello from JavaScript');
        """)
    }
}

在这个示例中,JavaScript 中调用 log 方法会同步执行,Native 代码会立即执行打印操作。

同步执行的优缺点

优点
  1. 简单直观

    • 同步调用方式更容易理解和调试,因为代码按照顺序执行,没有复杂的回调和异步逻辑。
  2. 立即获取结果

    • 调用完成后可以立即获取执行结果,无需等待异步回调,适用于需要立即处理结果的场景。
缺点
  1. 可能阻塞线程

    • 如果 JavaScript 代码或 Native 方法执行时间较长,可能会阻塞当前线程,影响应用的响应性。
  2. 影响性能

    • 在主线程上进行耗时的同步操作可能会导致 UI 卡顿和用户体验下降。

如何处理耗时操作

为了避免同步调用带来的阻塞和性能问题,可以将耗时操作放到后台线程中执行。

示例代码

import JavaScriptCore

class ViewController: UIViewController {
    var jsContext: JSContext!

    override func viewDidLoad() {
        super.viewDidLoad()

        jsContext = JSContext()

        // 定义一个耗时的 Native 方法
        let heavyTaskFunction: @convention(block) () -> String = {
            Thread.sleep(forTimeInterval: 2) // 模拟耗时操作
            return "Heavy task completed"
        }
        jsContext.setObject(heavyTaskFunction, forKeyedSubscript: "heavyTask" as NSString)

        // 在后台线程中执行 JavaScript 代码
        DispatchQueue.global().async {
            if let result = self.jsContext.evaluateScript("heavyTask()") {
                print("Result of heavy task: \(result.toString() ?? "")")
            }
        }
    }
}

在这个示例中,耗时操作被放到后台线程中执行,避免了阻塞主线程,确保了应用的响应性。

小结

使用 JavaScriptCore 进行跨语言调用时,调用通常是同步的。这种同步调用方式简单直观,可以立即获取结果,但可能会导致线程阻塞和性能问题。为了避免这些问题,可以将耗时操作放到后台线程中执行,确保应用的响应性和用户体验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1903969.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

洛谷 P3613 学习用map代替大大大数组的好题

题目链接:P3613 【深基15.例2】寄包柜 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目截图: 题意分析: 非常简单的存入和取出操作 唯一的 “难点” 在于 数组开不到 a[100007][100007],会暴内存 非常巧妙的引入 map 来解决…

Square Root SAM论文原理

文章目录 Square Root SAM论文原理核心原理SLAM问题的3种表示贝叶斯网络因子图(Factor graph)马尔科夫随机场(Markov Random Field, MRF) SLAM最小二乘问题&线性化因式分解 factorization矩阵与图(Matrices ⇔ Graphs)因式分解&变量消元(Factori…

深入理解 Kata Containers

目录 引言Kata Containers 的定义Kata Containers 的架构Kata Containers 的工作原理Kata Containers 的应用场景Kata Containers 在 CentOS 上的常见命令实验场景模拟总结 1. 引言 随着云计算和容器技术的迅猛发展,安全性和性能成为了用户关注的焦点。传统容器技…

STM32CubeMX实现4X5矩阵按键(HAL库实现)

为了实现计算器键盘,需要使用4X5矩阵按键,因此,我在4X4矩阵键盘上重新设计了一个4X5矩阵按键。原理图如下: 原理描述: 4X5矩阵按键,可以设置4个引脚为输出,5个引脚为输入模式,4个引…

如何屏蔽搜索结果特定网站?无限添加指定域名屏蔽解决方案

如何通过Chrome插件屏蔽某网站的搜索结果 在使用搜索引擎时,有时我们会希望屏蔽掉某些不想看到的网站。那么,我们可以通过安装油猴(Tampermonkey)插件,并使用特定脚本来实现这个目的。由于Chrome网上应用店可能无法打…

数据结构之“队列”(全方位认识)

🌹个人主页🌹:喜欢草莓熊的bear 🌹专栏🌹:数据结构 前言 上期博客介绍了” 栈 “这个数据结构,他具有先进后出的特点。本期介绍“ 队列 ”这个数据结构,他具有先进先出的特点。 目录…

ASCII码对照表【2024年汇总】

🍺ASCII相关文章汇总如下🍺: 🎈ASCII码对照表(255个ascii字符汇总)🎈🎈ASCII码对照表(Unicode 字符集列表)🎈🎈ASCII码对照表&#x…

Linux内核链表使用方法

简介: 链表是linux内核中最简单,同时也是应用最广泛的数据结构。内核中定义的是双向链表。 linux的链表不是将用户数据保存在链表节点中,而是将链表节点保存在用户数据中。linux的链表节点只有2个指针(pre和next),这样的话&#x…

中国星坤连接器:定制化服务,精准选型!

在当今快速发展的电子行业中,连接器作为电子设备中不可或缺的组成部分,其性能和品质直接影响到整个系统的性能表现。中国星坤连接器以其卓越的产品选型系统和质量保证,为全球客户提供了一站式的解决方案。 精准选型,快速定位 中国…

模板进阶:非类型模板参数,类模板特化,模板的编译分离

1. 非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。 非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常…

【python】python母婴数据分析模型预测可视化(数据集+论文+PPT+源码)【独一无二】

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化【获取源码商业合作】 👉荣__誉👈:阿里云博客专家博主、5…

vue-cli 脚手架详细介绍

4 vue-cli 脚手架 1 脚手架介绍 vue-cli也叫vue脚手架,vue-cli是vue官方提供的一个全局命令工具,这个命令可以帮助我们快速的创建一个vue项目的基础架子。 脚手架:搭建好的一个架子,我们在架子上进行开发 开箱即用零配置基于webpack、webpac…

13 学习总结:指针 · 其一

目录 一、内存和地址 (一)内存 (二)内存单元 (三)地址 (四)拓展:CPU与内存的联系 二、指针变量和地址 (一)创建变量的本质 (二…

【MySQL】逻辑架构与存储引擎

一、逻辑架构 1、MySQL逻辑架构 我们可以根据上图来对sql的执行过程进行分析 第一步:客户端与服务器建立一个连接,从连接池中分配一个线程处理SQL语句第二步:SQL接口接受SQL指令第三步:如果是5.7版本,就会先去缓存中…

SpringMVC(2)——controller方法参数与html表单对应

controller方法参数与html表单对应 0. User实体类 import org.springframework.format.annotation.DateTimeFormat;import java.io.Serializable; import java.util.Date; import java.util.List; import java.util.Map;public class User implements Serializable {private …

期末考试结束,老师该如何私发成绩?

随着期末考试的落幕,校园里又恢复了往日的宁静。然而,对于老师们来说,这并不意味着工作的结束,相反,一系列繁琐的任务才刚刚开始。 成绩单的发放,就是其中一项让人头疼的工作。家长们焦急地等待着孩子的考试…

【全面讲解如何安装Jupyter Notebook!】

🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…

springboot三层架构详细讲解

目录 springBoot三层架构0.简介1.各层架构1.1 Controller层1.2 Service层1.3 ServiceImpl1.4 Mapper1.5 Entity1.6 Mapper.xml 2.各层之间的联系2.1 Controller 与 Service2.2 Service 与 ServiceImpl2.3 Service 与 Mapper2.4 Mapper 与 Mapper.xml2.5 Service 与 Entity2.6 C…

【Spring Boot】关系映射开发(三):多对多映射

关系映射开发(三):多对多映射 1.创建实体1.1 创建 Student 实体1.2 创建 Teacher 实体 2.创建测试 在 多对多 关联关系中,只能通过 中间表 的方式进行映射,不能通过增加外键来实现。 注解 ManyToMany 用于关系的发出端…

【React Native优质开源项目】

🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…