尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

深入解析JS-Bridge:基于WKWebView的OC与JavaScript互调实战

深入解析JS-Bridge:基于WKWebView的OC与JavaScript互调实战 最近在技术社区里一个看似“跨界”的项目标题吸引了不少眼球——“老师们来用我做的OC调香工具”。乍一看这像是某个创意设计或艺术类工具但结合热搜词“OC”和热词“oc和javascript互相调用”其背后的技术内核立刻变得清晰起来。这其实是一个典型的前端与原生代码交互的实战项目。开发者口中的“OC”通常指Objective-C是iOS/macOS应用开发的核心语言。而“调香工具”则是一个充满想象力的比喻它可能是一个用于动态调整、混合、生成某种“配方”或“风格”的交互式应用。这个项目的核心挑战与价值就在于如何让运行在WebView里的JavaScript与底层的Objective-C代码安全、高效地“对话”从而实现丰富的原生能力调用。对于前端和移动端开发者而言跨语言调用JS-Bridge是老生常谈但也是永恒的痛点。很多教程只讲“怎么调通”却很少深入剖析“为什么这么设计”、“不同场景下如何选型”、“有哪些隐藏的坑”。本文将带你深入这个“调香工具”项目的技术腹地不仅还原一个完整的OC与JS互调实战更会系统性地拆解其原理、对比不同方案、提供避坑指南和工程化建议。无论你是想为H5页面添加原生能力还是希望用Web技术构建更灵活的移动端功能模块这篇文章都将提供可直接复用的解决方案。1. 这篇文章真正要解决的问题为什么一个“OC调香工具”值得专门写一篇文章它解决的远不止一个简单的函数调用问题。核心痛点Web的灵活性与原生能力的鸿沟。现代移动应用开发中纯原生开发迭代慢、热更新能力弱纯Web应用H5又难以调用摄像头、蓝牙、文件系统等设备核心能力体验上也存在差距。Hybrid混合开发模式因此成为许多业务的选择。而混合开发的核心就是建立一座连接JavaScript代表Web动态能力与Objective-C/Swift代表原生稳定能力的桥梁——即JS-Bridge。这个“调香工具”项目本质上就是一个自定义的、场景化的JS-Bridge实现案例。它可能面临以下具体问题如何从JS侧发起调用并传递复杂参数如对象、数组给OCOC方法执行完毕后如何将结果或错误异步地回传给JS如何设计一个安全、可控的通信协议防止任意JS代码调用敏感原生方法在WKWebView成为主流的今天如何适配其新的通信机制如何管理大量分散的OC暴露方法使其易于维护和扩展本文将围绕这些实际问题展开提供一个从原理到实践、从Demo到工程化的完整路径。适合读者包括有一定iOS开发基础希望深入理解JS-Bridge的前端或移动端开发者正在为Hybrid应用设计通信方案的技术负责人以及对Web与原生交互机制感兴趣的技术爱好者。2. 基础概念与核心原理在动手之前必须厘清几个关键概念和它们之间的关系。2.1 什么是OCObjective-CObjective-C是苹果生态iOS/macOS等过去长期使用的主要编程语言。它基于C语言增加了面向对象和Smalltalk风格的消息传递机制。虽然Swift已成为新宠但大量存量代码、第三方库以及系统底层API仍然以OC形式存在。因此与OC交互是接入苹果原生能力的必经之路之一。2.2 JS与OC互调的本质JavaScript运行在WebView如UIWebView或WKWebView的沙箱环境中而OC运行在应用的原生进程里。它们是两个完全隔离的执行环境。互调的本质是**进程间通信IPC**的一种特定形式通常通过以下方式实现URL Scheme拦截UIWebView时代常用JS通过改变iframe.src或发起location.href跳转触发一个自定义协议如myapp://methodName?paramvalue的请求。原生层拦截这个请求解析出要调用的方法和参数执行后可能再通过JavaScriptCore或stringByEvaluatingJavaScriptFromString:将结果回传。JavaScriptCore框架iOS 7苹果官方提供的框架可以在OC中创建JS上下文JSContext并将OC对象、方法直接暴露给这个上下文JS可以像调用普通JS函数一样调用它们。反之OC也可以执行JS代码并获取返回值。这是更现代、更高效的方案。WKWebView的MessageHandleriOS 8WKWebView提供了全新的WKScriptMessageHandler协议。JS通过window.webkit.messageHandlers.handlerName.postMessage()发送消息原生端通过对应的Handler接收并处理。这是目前WKWebView推荐的通信方式。2.3 “调香工具”的比喻解析在这个项目中“调香”可以类比为一个动态配置和触发原生能力的过程。香料参数JS侧提供的配置数据可能是颜色值、数值、字符串或复杂的JSON对象。调香台OC方法原生端实现的具体功能如调整图像滤镜参数、合成音频、计算数据等。成品香气结果OC方法执行后产出的结果再通过Bridge回传给JS侧进行展示或下一步处理。 整个“调香”流程就是一次完整的JS调用OC并获取结果的异步交互。3. 环境准备与前置条件为了复现和扩展这个“调香工具”你需要准备好开发环境。3.1 硬件与软件环境macOS开发iOS应用必须使用macOS系统。Xcode苹果官方IDE建议使用较新版本如Xcode 15及以上以确保对最新API和WKWebView的良好支持。iOS模拟器或真机用于运行和调试应用。3.2 项目创建与WebView选择打开Xcode选择“Create a New Project”。选择“App”模板填写项目名称如“JSOCPerfumeTool”语言选择Objective-C因为我们的重点是OC与JS互调。界面框架选择Storyboard或SwiftUI均可但本文示例将以Storyboard为基础。关键选择WebView类型。在iOS开发中你有两个主要选择UIWebView (已废弃)苹果已明确废弃不推荐在新项目中使用。WKWebView高性能、更安全、功能更丰富是现代Hybrid应用的标准选择。本文所有实现将基于WKWebView。3.3 准备前端测试页面我们将创建一个本地的HTML文件用于模拟“调香工具”的H5界面。将其放入项目资源中方便WebView加载。在Xcode项目中右键点击项目导航器选择“New File…” - “Empty”创建一个名为index.html的文件。将其放入项目的某个目录下例如拖拽到项目导航器的根目录并确保在弹出框中勾选“Copy items if needed”和你的应用Target。至此基础环境搭建完毕。接下来我们将进入核心的通信机制实现环节。4. 核心流程拆解实现WKWebView下的JS-OC互调我们将采用WKWebView的WKScriptMessageHandler方案这是目前最主流和推荐的方式。整个流程可以拆解为四个关键步骤。4.1 步骤一原生端OC注册消息处理器在OC代码中我们需要创建一个遵守WKScriptMessageHandler协议的对象并将其注册到WKWebView的配置中。这个处理器将负责接收来自JS的特定消息。4.2 步骤二JS端发起调用在HTML/JS代码中我们通过window.webkit.messageHandlers.handlerName.postMessage()方法向原生端发送消息。消息内容可以是一个字符串、数字、数组或对象。4.3 步骤三原生端处理消息并执行逻辑在消息处理器的回调方法中OC端会收到JS发送过来的消息。我们需要解析这个消息根据约定的格式识别出要执行的“调香”方法action和参数data然后调用对应的OC方法。4.4 步骤四原生端将结果回调给JS端OC方法执行完成后通常需要将结果成功的数据或失败的信息返回给JS。这需要通过WKWebView的evaluateJavaScript:completionHandler:方法执行一段JS代码来实现回调。下面我们通过完整的代码示例来串联这四个步骤。5. 完整示例与代码实现我们将创建一个简单的“调香工具”假设它有两个功能1. 混合颜色调色。2. 播放一段提示音。JS界面提供参数OC端执行具体逻辑并返回结果。5.1 项目结构准备首先在Storyboard的ViewController上添加一个WKWebView并建立IBOutlet连接。或者你也可以用代码创建。5.2 原生端OC核心代码实现文件路径ViewController.m#import ViewController.h #import WebKit/WebKit.h // 遵守 WKScriptMessageHandler 协议 interface ViewController () WKScriptMessageHandler, WKNavigationDelegate property (nonatomic, strong) WKWebView *webView; end implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self setupWebView]; [self loadLocalHTML]; } - (void)setupWebView { // 1. 创建 WKWebView 配置 WKWebViewConfiguration *config [[WKWebViewConfiguration alloc] init]; // 2. 创建用户内容控制器用于管理 JS 与 OC 交互 WKUserContentController *userContentController [[WKUserContentController alloc] init]; // 3. 注册消息处理器。nativeBridge 是约定好的 Handler 名称JS 端会使用它。 // self 作为处理器需要实现 WKScriptMessageHandler 协议。 [userContentController addScriptMessageHandler:self name:nativeBridge]; // 4. 将用户内容控制器赋值给配置 config.userContentController userContentController; // 5. 使用配置初始化 WKWebView CGRect frame self.view.bounds; self.webView [[WKWebView alloc] initWithFrame:frame configuration:config]; self.webView.navigationDelegate self; [self.view addSubview:self.webView]; } - (void)loadLocalHTML { // 加载项目内的 index.html 文件 NSString *htmlPath [[NSBundle mainBundle] pathForResource:index ofType:html]; if (htmlPath) { NSURL *htmlURL [NSURL fileURLWithPath:htmlPath]; [self.webView loadFileURL:htmlURL allowingReadAccessToURL:htmlURL.URLByDeletingLastPathComponent]; } } #pragma mark - WKScriptMessageHandler // 6. 处理从 JS 发来的消息 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { // message.name 就是我们注册时用的 nativeBridge // message.body 就是 JS 端调用 postMessage 时传递的参数 if ([message.name isEqualToString:nativeBridge]) { [self handleMessageFromJS:message.body]; } } - (void)handleMessageFromJS:(id)messageBody { // 7. 解析 JS 传递过来的消息体。我们约定它是一个字典。 if (![messageBody isKindOfClass:[NSDictionary class]]) { NSLog(JS消息格式错误应为字典); [self sendResultToJS:{} success:NO message:参数格式错误]; return; } NSDictionary *messageDict (NSDictionary *)messageBody; NSString *action messageDict[action]; // 操作类型如 mixColor, playSound id data messageDict[data]; // 操作参数 NSString *callbackId messageDict[callbackId]; // 回调ID用于匹配JS端的回调函数 // 8. 根据 action 分发到不同的原生方法 if ([action isEqualToString:mixColor]) { [self handleMixColorAction:data callbackId:callbackId]; } else if ([action isEqualToString:playSound]) { [self handlePlaySoundAction:data callbackId:callbackId]; } else { [self sendResultToJS:{callbackId: callbackId ?: } success:NO message:未知的action]; } } // 9. 处理“混合颜色”的 OC 方法 - (void)handleMixColorAction:(id)data callbackId:(NSString *)callbackId { // 模拟一个简单的颜色混合算法将传入的两种颜色字符串相加实际项目会是复杂的计算或调用系统API if ([data isKindOfClass:[NSDictionary class]]) { NSDictionary *colorDict (NSDictionary *)data; NSString *color1 colorDict[color1] ?: #000000; NSString *color2 colorDict[color2] ?: #FFFFFF; // 这里只是一个示例逻辑拼接颜色名 NSString *mixedColor [NSString stringWithFormat:混合自%和%, color1, color2]; // 构造成功结果 NSDictionary *result { mixedColor: mixedColor, hexCode: #7F7F7F // 模拟一个混合后的色值 }; [self sendResultToJS:{callbackId: callbackId, data: result} success:YES message:nil]; } else { [self sendResultToJS:{callbackId: callbackId} success:NO message:颜色参数格式错误]; } } // 10. 处理“播放声音”的 OC 方法 - (void)handlePlaySoundAction:(id)data callbackId:(NSString *)callbackId { // 这里应调用系统音频播放API例如 AudioToolbox。 // 为简化示例我们仅模拟播放成功。 NSLog(OC: 播放提示音); // 假设播放成功 [self sendResultToJS:{callbackId: callbackId, data: {status: played}} success:YES message:nil]; } // 11. 统一的将结果发送回 JS 的方法 - (void)sendResultToJS:(NSDictionary *)resultDict success:(BOOL)success message:(NSString *)errorMessage { // 构造一个标准的回调消息格式 NSMutableDictionary *msgToJS [NSMutableDictionary dictionaryWithDictionary:resultDict]; msgToJS[success] (success); if (errorMessage) { msgToJS[message] errorMessage; } // 将字典转换为 JSON 字符串 NSError *error; NSData *jsonData [NSJSONSerialization dataWithJSONObject:msgToJS options:0 error:error]; if (error) { NSLog(OC-JS 结果转换JSON失败: %, error); return; } NSString *jsonString [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; // 关键通过 evaluateJavaScript 执行 JS 代码触发 JS 端的回调 NSString *jsCode [NSString stringWithFormat:window.JSBridgeNative.onReceiveResult(%), jsonString]; [self.webView evaluateJavaScript:jsCode completionHandler:^(id _Nullable result, NSError * _Nullable error) { if (error) { NSLog(OC-JS 执行回调失败: %, error); } }]; } #pragma mark - 内存管理重要提示 // 12. 必须在视图控制器销毁前移除消息处理器防止循环引用 - (void)dealloc { if (_webView) { [_webView.configuration.userContentController removeScriptMessageHandlerForName:nativeBridge]; } } end5.3 前端JS/HTML测试页面实现文件路径index.html(位于项目资源目录)!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleOC调香工具 - H5界面/title style body { font-family: -apple-system, sans-serif; padding: 20px; } .section { margin-bottom: 30px; padding: 15px; border: 1px solid #ddd; border-radius: 8px;} input, button { padding: 10px; margin: 5px; font-size: 16px; } .result { margin-top: 10px; padding: 10px; background-color: #f5f5f5; border-radius: 5px; min-height: 20px;} .color-box { width: 50px; height: 50px; display: inline-block; margin: 0 10px; border: 1px solid #000;} /style /head body h1 OC调香工具实验台/h1 p通过下面的按钮调用原生Objective-C的能力。/p div classsection h21. 混合颜色 (OC计算)/h2 label颜色1: input typecolor idcolorPicker1 value#ff0000/label label颜色2: input typecolor idcolorPicker2 value#0000ff/label br button onclickcallNativeMixColor()开始调色/button div classresult idcolorResult 等待调色结果... /div div 预览: div classcolor-box idcolorPreview1 stylebackground-color: #ff0000;/div div classcolor-box idcolorPreview2 stylebackground-color: #0000ff;/div div classcolor-box idcolorPreviewMixed stylebackground-color: #7F7F7F;/div /div /div div classsection h22. 播放提示音 (OC播放)/h2 button onclickcallNativePlaySound()播放提示音/button div classresult idsoundResult 等待播放状态... /div /div script // 13. 全局回调函数映射表用于管理异步回调 window.JSBridgeNative { _callbacks: {}, _callbackId: 0, // 提供给OC调用的统一结果接收函数 onReceiveResult: function(result) { console.log(JS收到OC回调:, result); var callbackId result.callbackId; var success result.success; var data result.data; var message result.message; var callback this._callbacks[callbackId]; if (callback) { if (success) { callback.resolve(data); } else { callback.reject(new Error(message || OC调用失败)); } // 调用后删除防止内存泄漏 delete this._callbacks[callbackId]; } else { console.warn(未找到对应的回调ID:, callbackId); } }, // 发送消息到原生的通用方法 postMessage: function(action, data) { return new Promise((resolve, reject) { // 生成唯一的回调ID var callbackId cb_ (this._callbackId) _ Date.now(); // 存储resolve和reject this._callbacks[callbackId] { resolve, reject }; // 构造发送给OC的消息体 var message { action: action, data: data, callbackId: callbackId }; // 14. 核心调用通过 WKWebView 的 messageHandlers 发送 // 注意nativeBridge 必须与OC端注册的handler名称一致 if (window.webkit window.webkit.messageHandlers window.webkit.messageHandlers.nativeBridge) { window.webkit.messageHandlers.nativeBridge.postMessage(message); } else { reject(new Error(原生桥接未就绪或环境不支持)); } }); } }; // 15. 具体业务调用函数 function callNativeMixColor() { var color1 document.getElementById(colorPicker1).value; var color2 document.getElementById(colorPicker2).value; // 更新预览 document.getElementById(colorPreview1).style.backgroundColor color1; document.getElementById(colorPreview2).style.backgroundColor color2; document.getElementById(colorResult).innerHTML 正在调用OC进行颜色混合计算...; // 调用通用方法返回一个Promise window.JSBridgeNative.postMessage(mixColor, { color1: color1, color2: color2 }) .then(function(result) { // OC调用成功 var html 混合成功br结果描述${result.mixedColor}br模拟色值${result.hexCode}; document.getElementById(colorResult).innerHTML html; document.getElementById(colorPreviewMixed).style.backgroundColor result.hexCode; }) .catch(function(error) { // OC调用失败 document.getElementById(colorResult).innerHTML 调色失败 error.message; }); } function callNativePlaySound() { document.getElementById(soundResult).innerHTML 正在请求OC播放声音...; window.JSBridgeNative.postMessage(playSound, { volume: 0.8 }) .then(function(result) { document.getElementById(soundResult).innerHTML 播放状态${result.status}; }) .catch(function(error) { document.getElementById(soundResult).innerHTML 播放失败 error.message; }); } // 页面加载完成后的初始化 window.onload function() { console.log(调香工具H5页面加载完毕JSBridge已初始化。); }; /script /body /html6. 运行结果与效果验证完成上述代码后按照以下步骤运行和验证运行项目在Xcode中选择一个模拟器如iPhone 15 Pro或连接真机点击运行▶️按钮。观察启动应用启动后WKWebView会加载本地的index.html文件你会看到一个简单的H5界面包含两个功能区域“混合颜色”和“播放提示音”。测试功能一混合颜色点击颜色选择器分别选择两种颜色。点击“开始调色”按钮。预期结果JS控制台通过Xcode的Console或Safari的Web Inspector会打印出JS收到OC回调:的消息其中包含OC返回的混合结果。页面上“等待调色结果...”的区域会更新为“混合成功结果描述混合自#xxxxxx和#xxxxxx 模拟色值#7F7F7F”。右侧的第三个颜色预览方块会变为灰色(#7F7F7F)。验证点这证明了JS成功将颜色参数color1,color2发送给了OCOC处理模拟混合后又将结果mixedColor,hexCode异步地传回了JS并由JS更新了UI。测试功能二播放提示音点击“播放提示音”按钮。预期结果Xcode的Console中会输出OC: 播放提示音的日志。页面上“等待播放状态...”的区域会更新为“播放状态played”。验证点这证明了JS可以触发OC执行非UI逻辑这里是模拟播放音频并且OC能通知JS执行完成。错误处理测试可选你可以尝试修改JS代码发送一个不存在的action如unknownAction给OC。预期结果JS会收到一个包含success: false和错误信息的回调页面会显示“调色失败未知的action”。如果运行失败第一步应该检查Xcode Console查看是否有OC端的错误日志如JSON解析失败、找不到方法等。Safari Web Inspector在模拟器或真机上启用Safari的“开发”菜单检查JS控制台是否有错误如window.webkit.messageHandlers未定义以及网络请求是否正常。Bridge注册确认OC端addScriptMessageHandler的namenativeBridge与JS端postMessage的目标window.webkit.messageHandlers.nativeBridge完全一致。7. 常见问题与排查思路在实际项目中JS-OC互调会遇到各种问题。下表总结了常见问题及其解决方法问题现象可能原因排查方式解决方案JS调用无反应OC收不到消息1. WKWebView未使用自定义Configuration。2. 消息处理器未注册或名称不匹配。3. JS代码在WebView加载完成前执行。1. 检查setupWebView方法确认使用了带WKUserContentController的config。2. 对比OC的addScriptMessageHandler:name:和JS的window.webkit.messageHandlers.name。3. 在JS中console.log(window.webkit)检查对象是否存在。1. 确保使用WKWebViewConfiguration初始化WebView。2. 确保name字符串完全一致大小写敏感。3. 将JS调用代码放在window.onload或DOMContentLoaded事件中。OC可以收到消息但解析参数出错1. JS传递的参数不是合法JSON或格式不符合约定。2. OC端未对message.body类型做判断。1. 在OC的handleMessageFromJS:方法中打印messageBody的类型和内容。2. 在JS调用前用JSON.stringify确保传递的是对象。1. 约定并严格遵循通信协议如{action, data, callbackId}。2. OC端使用isKindOfClass:进行类型判断并做好错误处理。OC执行成功但JS回调不执行1.evaluateJavaScript:调用失败或JS代码有语法错误。2. JS端的全局回调函数onReceiveResult未正确定义或名称不一致。3.callbackId不匹配找不到对应的Promise。1. 检查evaluateJavaScript:的completionHandler查看error信息。2. 检查JS中window.JSBridgeNative.onReceiveResult函数是否定义。3. 检查OC回传的callbackId与JS发送的是否一致。1. 确保OC构造的JS代码字符串语法正确。2. 确保JS全局对象和函数名与OC代码中硬编码的字符串一致。3. 使用更健壮的回调管理机制如超时清理。内存泄漏控制器不释放addScriptMessageHandler:会强引用selfViewController导致循环引用。在控制器的dealloc方法中设置断点观察是否执行。必须在控制器销毁前如dealloc或viewDidDisappear:中调用removeScriptMessageHandlerForName:。真机上运行正常模拟器上报错可能涉及文件访问权限或模拟器特定问题。检查加载本地HTML文件的路径是否正确fileURL访问权限是否已通过allowingReadAccessToURL:授予。使用[[NSBundle mainBundle] pathForResource:ofType:]获取路径并授予其目录的读取权限。传递数据量较大时失败postMessage对消息体大小可能有限制虽然通常很大。尝试传递一个非常大的JSON对象观察是否失败。对于超大数据考虑分片传输或在OC端通过其他方式如临时文件、共享内存获取数据。8. 最佳实践与工程化建议将简单的互调Demo升级为可维护、安全、高效的工程方案需要考虑以下几点8.1 设计安全的通信协议白名单机制不要在OC端无条件执行所有JS请求。维护一个合法的action白名单只有名单内的方法才允许被调用。参数校验与过滤对JS传入的data进行严格的类型和范围校验防止注入攻击。权限控制某些敏感操作如访问通讯录、发送短信需要额外的用户授权应在OC端统一处理权限逻辑不要依赖JS传递的“权限标志”。8.2 实现健壮的Bridge管理层统一入口与路由像示例中handleMessageFromJS:方法一样设计一个统一的消息分发中心。随着业务增长可以引入路由表将action映射到对应的Handler类或方法。Promise封装在JS端使用Promise封装异步调用极大地改善了开发体验避免了回调地狱。示例中已实现。回调超时管理为每个callbackId设置一个超时定时器超时后自动清理_callbacks中的对应项并触发reject避免内存泄漏和悬置Promise。8.3 性能优化消息序列化postMessage会自动序列化消息。对于复杂对象确保其可序列化如避免包含函数、循环引用。批量操作如果JS需要连续调用多个OC方法可以考虑设计一个支持批量操作的action减少通信次数。避免频繁通信对于实时性要求不高的数据同步可以考虑在JS端缓存或使用其他效率更高的方式如JavaScriptCore的直接绑定。8.4 与JavaScriptCore方案对比与选型除了WKScriptMessageHandlerJavaScriptCore是另一个强大选择。它允许你将OC对象或Block直接暴露为JS上下文中的全局对象/函数。如何选择使用WKScriptMessageHandler当你主要使用WKWebView。通信逻辑相对独立你希望JS和OC代码解耦。通信频率不是极端高频。你需要更好的安全隔离默认情况下JS不能直接访问原生对象。使用JavaScriptCore当你需要极高性能的频繁调用如游戏逻辑、大量计算。你希望JS能够以更“自然”的方式像调用本地函数一样调用OC。你的应用可能同时支持UIWebView尽管已废弃和WKWebView而JavaScriptCore两者都支持。注意在WKWebView中直接使用JavaScriptCore与Web内容交互较为复杂通常需要借助evaluateJavaScript:将JSContext创建在Web线程或者通过WKUserScript注入。对于大多数Hybrid场景WKScriptMessageHandler的抽象层次更合适。8.5 面向Swift的迁移如果你的项目使用Swift原理完全相通。你需要让Swift类遵循WKScriptMessageHandler协议。在userContentController(_:didReceive:)方法中处理消息。注意在deinit中移除消息处理器。使用JSONSerialization处理数据转换。Swift版本通常代码更简洁但核心的通信模型和最佳实践不变。通过以上步骤你已经从零构建了一个功能完整、结构清晰的“OC调香工具”原型。它不仅仅是一个Demo更是一个可扩展的JS-Bridge通信框架的雏形。你可以在此基础上增加更多的“香料”OC方法设计更复杂的“调香配方”JS交互流程从而为你的Hybrid应用注入强大的原生动力。理解这套机制是打通Web灵活性与原生性能的关键一步。
返回列表