使用 JavaScriptCore 进行跨语言调用

使用 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.mfbz.cn/a/773824.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

视图库对接系列(GA-T 1400)九、视图库对接系列(本级)机动车数据推送

背景 在上几章中,我们已经可以将视图库的平台写到我们的数据库中了。 换句话说就已经接入我们的平台了,这几期的话,我们就对接设备, 将设备的数据接入到我们平台来。 机动车数据推送 接入机动车数据推送相对比较简单,我们只需要实现对应的接口就ok了。 具体如图: 有增…

77. UE5 RPG 创建角色的技能栏

在前面的文章里,我们实现了角色属性技能和场景。接下来,我们要优化角色显示UI,在屏幕底部显示角色血量,蓝量,技能和经验值。 创建新的用户控件 选择创建新的控件蓝图 父类为我们自定义的RPGUserWidget,这…

这样拼板帮你省近万元,堪称PCB工程师成本终结者!

别再被骗了,打PCB板价格高不是单价高!而是你的拼板导致利用率太低了! 今天给大家讲个小故事,教大家如何省钱...... 一个爽朗的晴天,我听闻同事说有客户对他吐槽打板子价格太高,说着说着就开始吹起了牛逼...…

【论文阅读】VASA-1: Lifelike Audio-Driven Talking FacesGenerated in Real Time

整体框架。不直接生成视频帧,而是在潜在空间中生成整体面部动态和头部运动,条件是音频和其他信号。给定这些运动潜在编码,通过面部解码器生成视频帧,还接受从输入图像中提取的外观和身份特征作为输入。 构建了一个面部潜在空间并…

【C#】ProgressBar进度条异步编程思想

1.控件介绍 进度条通常用于显示代码的执行进程进度,在一些复杂功能交互体验时告知用户进程还在继续。 在属性栏中,有三个值常用: Value表示当前值,Minimum表示进度条范围下限,Maximum表示进度条范围上限。 2.简单实…

【网络安全】第8讲 网络安全协议(笔记)

一、网络安全协议概述 1、协议 是指两个或多个以上参与者为完成某项特定的任务而采取的一系列步骤。 2、网络协议 是指计算机网络中通信各方关于如何进行数据交换所达成的一致性规则、标准或约定的集合,即由参与通信的各方按确定的步骤做出一系列通信动作&#xff…

Linux系统安装青龙面板结合内网穿透实现使用公网地址远程访问

文章目录 前言一、前期准备本教程环境为:Centos7,可以跑Docker的系统都可以使用。本教程使用Docker部署青龙,如何安装Docker详见: 二、安装青龙面板三、映射本地部署的青龙面板至公网四、使用固定公网地址访问本地部署的青龙面板 …

Embedded Coder生成C代码注释

学习目标 本教程将向您说明如何生成包含以下内容的代码: 在函数前注中包含函数签名和函数帮助文本。包含 MATLAB 源代码,以带有可追溯性标记的注释表示。在代码生成报告中,可追溯性标记链接到对应的 MATLAB 源代码。 前提条件 要完成本教…

入门PHP就来我这(纯干货)08

~~~~ 有胆量你就来跟着路老师卷起来! -- 纯干货,技术知识分享 ~~~~ 路老师给大家分享PHP语言的知识了,旨在想让大家入门PHP,并深入了解PHP语言。 1 PHP对象的高级应用 1.1 final关键字 final 最终的、最后的。被final修饰过的类…

固相提取铕和铀

固相萃取(Solid Phase Extraction,SPE)是一种常用的化学分离技术,它利用固体吸附剂(固定相)与样品中的目标化合物(流动相)之间的相互作用力,将目标化合物从样品中分离出来…

JVM的五大内存区域

JVM的五大内存区域 JVM内存区域最粗略的划分可以分为 堆 和 栈 ,当然,按照虚拟机规范,可以划分为以下几个区域: JVM内存分为线程独享区和线程共享区, 其中 方法区 和 堆 是线程共享区, 虚拟机栈, 本地方法…

为什么需要做网络安全服务?

网络安全服务之所以重要,是因为它在保护数字资产、维护企业运营、确保法规遵从、防范恶意行为以及建立信任等方面扮演着关键角色。以下是一些主要的理由: 保护核心资产和数据: 数字化转型使得企业数据变得极其宝贵,包括知识产权、…

竞赛选题 协同过滤电影推荐系统

文章目录 1 简介1 设计概要2 课题背景和目的3 协同过滤算法原理3.1 基于用户的协同过滤推荐算法实现原理3.1.1 步骤13.1.2 步骤23.1.3 步骤33.1.4 步骤4 4 系统实现4.1 开发环境4.2 系统功能描述4.3 系统数据流程4.3.1 用户端数据流程4.3.2 管理员端数据流程 4.4 系统功能设计 …

开发在线教育项目-在线课程视频网站开发

用了哪些技术 后端技术 springboot3 security权限框架(后台)mybatisPlus框架jwt生成tokeneasyexcel导入导出递归查询拦截器校验tokenredis的zset做排行榜功能redis的list做最新课程的功能redis做为缓存技术redis作为计数器,实时记录浏览量&…

极狐GitLab 将亮相2024空天信息大会暨数字地球生态峰会,携手中科星图赋能空天行业开发者

GitLab 是一个全球知名的一体化 DevOps 平台,很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab :https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版,专门为中国程序员服务。可以一键式部署…

【Proteus】按键的实现『⒉种』

🚩 WRITE IN FRONT 🚩 🔎 介绍:"謓泽"正在路上朝着"攻城狮"方向"前进四" 🔎🏅 荣誉:2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评…

微信小程序毕业设计-走失人员的报备平台系统项目开发实战(附源码+论文)

大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:微信小程序毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设计…

【Python学习】流程控制、函数与类详解

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 引言 Python作为一门强大而又简洁的编程语言,提供了丰富的工具和结构来帮助开发者编写清晰、高效的代码。在本文中…

企业搭建知识库:解锁无限潜力的钥匙

在当今这个信息爆炸的时代,企业如何高效地管理、传播与利用知识,已成为衡量其竞争力的重要标尺。知识库,作为这一背景下的产物,正逐步成为企业不可或缺的数字资产。它不仅是一个自助式的数字门户,更是连接员工、客户与…

加入AIGC的小艺还有这些大用处 快来看

说到毕业,有不舍、有迷茫也有期待,在这种复杂的情绪里,手机里的小艺,简直是贴心小棉袄,给了我很多依靠,让我能勇敢的往前走。 在离别时候有太多的不舍,想要写段寄语记录下来,这时候小…
最新文章