惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
博客园_首页
H
Help Net Security
T
Tailwind CSS Blog
S
SegmentFault 最新的问题
GbyAI
GbyAI
Scott Helme
Scott Helme
D
Docker
Hacker News: Ask HN
Hacker News: Ask HN
P
Privacy & Cybersecurity Law Blog
Jina AI
Jina AI
雷峰网
雷峰网
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Spread Privacy
Spread Privacy
G
GRAHAM CLULEY
C
Cisco Blogs
The Hacker News
The Hacker News
F
Full Disclosure
Y
Y Combinator Blog
Blog — PlanetScale
Blog — PlanetScale
Recent Announcements
Recent Announcements
G
Google Developers Blog
量子位
K
Kaspersky official blog
Cisco Talos Blog
Cisco Talos Blog
The Cloudflare Blog
A
About on SuperTechFans
C
Cybersecurity and Infrastructure Security Agency CISA
Last Week in AI
Last Week in AI
博客园 - 三生石上(FineUI控件)
Microsoft Security Blog
Microsoft Security Blog
Martin Fowler
Martin Fowler
T
Tenable Blog
P
Palo Alto Networks Blog
H
Heimdal Security Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
W
WeLiveSecurity
Schneier on Security
Schneier on Security
The Register - Security
The Register - Security
F
Fortinet All Blogs
Stack Overflow Blog
Stack Overflow Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
The Blog of Author Tim Ferriss
N
News and Events Feed by Topic
Hugging Face - Blog
Hugging Face - Blog
小众软件
小众软件
V
V2EX
爱范儿
爱范儿

Oragekk's Blog

OpenSpec 技术分享:用规格驱动 AI 编程 ChatGPT&Codex订阅教程 一个 waline 评论系统bug引发的思考 Jenkins 远程触发构建踩坑记 Git SSH 密钥配置 初识Rust vuepress-plugin-meting2 谷歌发布多平台应用开发神器Project IDX!PaLM 2加持 Vue常见优化手段 Vue2响应式原理解析 Dart 中的并发 Flutter 工作原理 如何利用GitHub Action提交URL到搜索引擎 提交URL到搜索引擎(百度、Bing、Google) GitHub Actions 使用介绍 素材设计 前端-Q&A 浏览器的事件循环 你不知道的 CSS 之包含块 CSS 属性计算过程 Vercel deploy忽略指定分支 评论插件 Waline 之邮件通知配置 公开API 终端究极美化iTerm2+Pure 使用Bing API提交网站URL Flutter 基础大集合 关于本站 关于本站 关于我 Markdown 展示 使用n命令管理node版本 幻灯片页 ReactNative State(状态) ReactNative开发环境配置,ES6语法介绍 ReactNative介绍 更优雅强大的终端ZSH 神经网络模型训练 YYCache优秀的缓存设计 NSError WCDB漫谈 优雅的实现TableViewCell单选 初探机器学习框架CoreML 深入理解swift中闭包的捕捉语义 ijkPlayer 集成 iOS 配置https iOS timelineLogistics iOS Cookie的配置及使用 WKWebView拦截URL WKWebView使用及自适应高度 textfield限制输入字符 评论系统从多说迁移到disqus指南 利用Runtime进行快速归档 iOS 10.3 keychain 重大更新 Cell的accessoryType属性标记单元格之后,出现的重用问题 通过UserAgent判断设备 AFNetworking A memory leak 一人一句宋词 OC 中的枚举类型 iOS - Image compression algorithm iOS程序启动原理(下) iOS程序启动原理(上) NSOperatioin TableView性能优化 Runloop Test Three ways to call Update Cocoapods 1.1.1 减小iOS-App或者静态库体积 Jekyll旧站回忆 JavaScript ES6 CommonJS,RequireJS,SeaJS 归纳笔记 Unix/Linux 扫盲笔记
WebViewJavascriptBridge
Oragekk · 2018-08-05 · via Oragekk's Blog

最近一直在忙,今天抽空写一下 H5 和 Native 的交互

一、选择

  • 项目本身 webview 使用的是 WKWebview,其实 WKWebview 自带的 messageHandle 也可以满足此需求
  • JSContext,源自于 JavaScriptCore 框架中的东西,最后不使用此方案源于一下几点
    • 但是其中繁杂的字符串使用,让我觉的可能会由于粗心出现不可预知的错误
    • 加载时机的问题,当你重新 loadrequest 的时候,会导致 js 注入失败
    • 回调方法略复杂
  • JavaScriptBridge,最后选择此库源于以下几点
    • 使用简单,注册完毕之后设置完代理,只需要负责注册方法和调用方法
    • 回调简单,两端回调 responsecallback 包含在注册的方法中。使用 block
    • 三端通用,JavaScript 和 iOS、Android 都可以(Android 版本库
    • Ps :关于 Android 版本库,其中很多是按照 iOS 版的 JavaScriptBridge 改写的。但是其中有很多问题,尤其是各种调用时机问题,上面的链接是经过我旁边的 Android 小哥试了四五个版本之后发现的,修复了各种改写版的问题

二、使用

  • 首先需要引入 WebViewJavascriptBridge 库
#import "WebViewJavascriptBridge.h"
  • 初始化,此处为了方便子类使用,所以在基类中注册 bridge,并 return bridge 对象,方便子类调用
#pragma mark - 桥接

- (void)InitializeWebViewJavascriptBridge {
    // 注册桥接
    self.bridge = [SWHybridManager setJavaScriptBridgeWithWebView:self.webView controller:self];
}

[WKWebViewJavascriptBridge enableLogging];
WKWebViewJavascriptBridge *bridge = [WKWebViewJavascriptBridge bridgeForWebView:webView];
[bridge setWebViewDelegate:controller];
  • 注册方法供 JavaScript 调用
__weak typeof(controller)wController = controller;
/****************************公共方法注册-Start*********************/
    //MARK:打开窗体
    [bridge registerHandler:HandlerFunctionNameOpenWindow handler:^(id data, WVJBResponseCallback responseCallback) {
        __strong typeof(wController)sController = wController;
        NSLog(@"\n调用了openWindow: %@", data);
        NSDictionary *dict = (NSDictionary *)data;
        SWOpenWindowModel *model = [SWOpenWindowModel yy_modelWithDictionary:dict];
        [self pushViewController:sController data:model responseCallback:responseCallback];
    }];
  • 调用 JavaScript 方法
[self.bridge callHandler:callFunctionNameGetSearchKeyWord data:json];

三、方法名定义

  • 因为方法名的定义是字符串,所以建议采用常量字符串,防止拼写错误
  • 其次不建议采用宏定义
  • 我采用以下方法
  • 桥接管理类的.h
/**打开窗体 */
FOUNDATION_EXPORT  NSString *const HandlerFunctionNameOpenWindow;
/** 关闭窗口*/
FOUNDATION_EXPORT  NSString *const HandlerFunctionNameCloseWindow;
  • 桥接管理类的.m
/**打开窗体 */
NSString *const HandlerFunctionNameOpenWindow = @"openWindow";
/** 关闭窗口*/
NSString *const HandlerFunctionNameCloseWindow = @"closeWindow";
  • 使用时直接使用常量字符串即可
  • 注意点:如类似我使用在基类传入控制器和 webview 到管理类中,在类中使用 controller 要注意循环引用,否则会导致控制器无法释放
+ (WKWebViewJavascriptBridge *)setJavaScriptBridgeWithWebView:(WKWebView *)webView controller:(__kindof SWBaseWebViewController *)controller;

__weak typeof(controller)wController = controller; // 弱引用传入控制器
__strong typeof(wController)sController = wController; // 在block内部强引用

四、数据传输

  • iOS 端直接返回字典即可
  • 我代码中是返回 json 字符串,为了与 Android 统一,方便 H5 解析数据

五、JavaScript 代码

function setupWebViewJavascriptBridge(callback) {
  if (window.WebViewJavascriptBridge) {
    return callback(WebViewJavascriptBridge);
  }
  if (window.WVJBCallbacks) {
    return window.WVJBCallbacks.push(callback);
  }
  window.WVJBCallbacks = [callback];
  var WVJBIframe = document.createElement("iframe");
  WVJBIframe.style.display = "none";
  WVJBIframe.src = "https://__bridge_loaded__";
  document.documentElement.appendChild(WVJBIframe);
  setTimeout(function () {
    document.documentElement.removeChild(WVJBIframe);
  }, 0);
}
setupWebViewJavascriptBridge(function (bridge) {
  /* Initialize your app here */

  bridge.registerHandler("JS Echo", function (data, responseCallback) {
    console.log("JS Echo called with:", data);
    responseCallback(data);
  });
  bridge.callHandler(
    "ObjC Echo",
    { key: "value" },
    function responseCallback(responseData) {
      console.log("JS received response:", responseData);
    }
  );
});

六、注意事项

  • 如果产生调用不通的问题,多为 JavaScript 调用时机问题
  • 注意桥接的代理