笔者刚开始学习 Vue,为了熟悉 Vue 和 iOS 的桥接及回调的交互,写了以下文章来了解一下 Vue 如何和 iOS 进行桥接交互传参
iOS 项目
一. 初始化创建 WKWebView 容器
目前iOS给前端提供的容器,均依赖于 WKWebView,以下实现方式是根据 WKWebView 自身的 handerMessage 来和前端建立通信。
浅解 WKWebView 的系统API
1. WKWebViewConfiguration
/*!
@abstract A copy of the configuration with which the web view was
initialized.
*/
@property (nonatomic, readonly, copy) WKWebViewConfiguration *configuration;
WKWebViewConfiguration 主要为了添加 WKWebview 配置信息
2. WKUserScript 用于进行JavaScript注入
/*!
A @link WKUserScript @/link object represents a script that can be injected into webpages.
*/
WKUserScript:用于进行 JavaScript 注入
3. WKUserContentController
/*!
A WKUserContentController object provides a way for JavaScript to post
messages to a web view.
The user content controller associated with a web view is specified by its
web view configuration.
*/
WKUserContentController:这个类主要用来做 native 与 JavaScript 的交互管理, 用来处理 iOS 和前端的桥接方法触发响应
// 这个类主要用来做native与JavaScript的交互管理
WKUserContentController * userController = [[WKUserContentController alloc] init];
// 注册一个name为jsToOcNoPrams的js方法 设置处理接收JS方法的对象
// 此方法 webViewApp 即和前端约定好的,handerMessage 方法名
[userController addScriptMessageHandler:scriptMessageDelegate name:@"webViewApp"];
4. WKScriptMessageHandler
WKScriptMessageHandler:这个协议类专门用来处理监听 JavaScript 方法从而调用原生 OC 方法,和 WKUserContentController 搭配使用。
/*! A class conforming to the WKScriptMessageHandler protocol provides a
method for receiving messages from JavaScript running in a webpage.
*/
二. WKWebView 的 WKNavigationDelegate 及 WKUIDelegate 代理方法
1. WKNavigationDelegate 主要处理一些跳转、加载处理操作
// 页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
}
// 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
}
// 当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
}
// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
}
//提交发生错误时调用
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
[self.progressView setProgress:0.0f animated:NO];
}
// 接收到服务器跳转请求即服务重定向时之后调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation {
}
// 根据WebView对于即将跳转的HTTP请求头信息和相关信息来决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
}
// 根据客户端受到的服务器响应头以及response相关信息来决定是否可以跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
}
//进程被终止时调用
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView{
}
2. WKUIDelegate :主要处理JS脚本,确认框,警告框等
/**
* web界面中有弹出警告框时调用
* @param webView 实现该代理的webview
* @param message 警告框中的内容
* @param completionHandler 警告框消失调用
*/
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {}
// 确认框
// JavaScript调用confirm方法后回调的方法 confirm是js中的确定框,需要在block中把用户选择的情况传递进去
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{}
// 输入框
// JavaScript调用prompt方法后回调的方法 prompt是js中的输入框 需要在block中把用户输入的信息传入
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{}
// 页面是弹出窗口 _blank 处理
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {}
3. 监听网页加载进度progress 及网页的 title
estimatedProgress 用来监听网页加载进度,自定义 progress 来显示网页的加载进度条,提升使用体验。
添加
// 监听加载进度
[_mainWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
// 添加监测网页标题title的观察者
[_mainWebView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:nil];
移除
- (void)dealloc {
// 移除观察者
[self.mainWebView removeObserver:self forKeyPath:@"estimatedProgress"];
[self.mainWebView removeObserver:self forKeyPath:@"title"];
}
至此,一个默认的 WKWebView 容器创建好了。
Vue 项目
一. 使用 Vue CLI 初始化创建一个 vue2 版本的默认项目
启动终端
cd Desktop
vue create vue_demo
-- -- --
创建成功后,npm run serve,启动服务,加载本地服务的 ip 地址,http://--.---.--.---:8080/ 在 刚创建的 iOS 容器内 已经可以显示 Vue 页面了
二. 前端 与 iOS 交互
1. 建立通信桥接通道, iOS 调用实现 Vue 的方法
iOS 端代码
// 注册一个 name 为 webViewApp 的 JS 方法 处理接收 JS 方法的对象
[userController addScriptMessageHandler:scriptMessageDelegate name:@"webViewApp"];
Vue 端代码
// 直接调用 window 方法即可,webViewApp 为前端和原生那边统一定义的 方法名
window.webkit.messageHandlers.webViewApp.postMessage
2. iOS 传值给前端
统一定义了一个回调接收的方法 iosCallback,可实现 iOS 传值给前端,客户端可以拿到前端body传参JSON里面的方法名,去实现对应的功能
原生代码实现看下面截图
前端给客户端传参可以为字符串、对象、JSON.stringify字符串
Vue 代码实现看下面截图, 一般我们会在 body 里面传 action:方法名,iOS那边拿到这个方法名,去实现对应的功能。
iOS 传值给前端有个需要注意的点
如果直接传值字符串的话,使用以下方式
// js 接收
直接输出 value即可。
如果iOS传值的是UTF8的JSON字符串的话
NSString *ocDataStr = [NSString
console.log("得到原生传值结果:" + JSON.stringify(value));