swift中WKWebView和H5的简单交互

it2023-01-25  57

WKWebView

1. 创建WKWebView2 IOS调用H53. H5调用原生3.1 通过连接3.2 通过方法3.3 在网页加载之前,传递值给H5

1. 创建WKWebView

let configuration = WKWebViewConfiguration.init() configuration.selectionGranularity = WKSelectionGranularity.dynamic //允许播放视频 configuration.allowsInlineMediaPlayback = true let preferrnce = WKPreferences.init(); //设置是否支持javaScript preferrnce.javaScriptEnabled = true //不用通过交互是否可以打开窗口 preferrnce.javaScriptCanOpenWindowsAutomatically = true configuration.preferences = preferrnce // 通过JS与webview内容交互 configuration.userContentController = WKUserContentController() let wkWebview = WKWebView.init(frame: frame, configuration: configuration) wkWebview.navigationDelegate = self wkWebview.uiDelegate = self wkWebview.allowsBackForwardNavigationGestures = true //二级网页是否可以左划返回

2 IOS调用H5

我们可以通过以下方法来调用H5的方法,已获取H5标题为例: //1.需要发送一个js命令获取网页的标题 webView.evaluateJavaScript("document.title") { (data, error) in } IOS调用vue中的方法,那么在vue中,只需要将方法绑定到window中即可,ios就能够调用到 //vue中需要注册的方法 created(){ //供iso调用前需要绑定到window上 window.AppToHTMLUserInfo = this.AppToHTMLUserInfo; }, //OC中调用 let methodName = "AppToHTMLUserInfo(\(lgoniInfoString()))" wkWebView!.evaluateJavaScript(methodName) { (data, error) in print("data=====\(data) error=========\(error)") } 如何实现实时的获取H5的标题,并且显示在导航栏: 首先我们知道WKWebView有一个属性title(支持KVO),这个属性值就是当前H5页面的标题当我们发送指令获取H5标题的时候,WKWebView会把H5的标题获取并赋值给这个title属性想要实时获取H5标题,只需使用KVO监听title舒心即可 //2.需要使用webview来监听标题的实时改变 wkWebView.addObserver(self, forKeyPath: "title", options: NSKeyValueObservingOptions.new, context: nil) override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if keyPath == "title" { if (object as! WKWebView) == wkWebView { titlelable.text = wkWebView.title } } else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) } }

3. H5调用原生

3.1 通过连接

H5和app端可以置顶一种连接的形式,当app打开网页时 在delegate方法中截取连接,判断是否是定好的链接,然后再解析,并调用原生方法:

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { print("在发送请求之前,决定是否跳转=====\(navigationAction.request.url)") do { let url = try String.init(contentsOf: navigationAction.request.url!) if url.starts(with: "xiangzhengapp") { //表示需要调用方法 print("取消访问这个地址====") decisionHandler(WKNavigationActionPolicy.cancel) } } catch { print("webView--error=======\(error)") } //表示允许 decisionHandler(WKNavigationActionPolicy.allow) }

3.2 通过方法

通过调用非方法格式如下: // JS调OC,需要 H5端统一如下写法,方法名就是交互的名称,数据就是JS给OC传的值 window.webkit.messageHandlers.<方法名>.postMessage(<数据>) 首先我们需要再app单注册和H5定义好的方法名称注册方法configuration.userContentController.add(),在不适用之后需要移出,不然会形成循环引用 // 通过JS与webview内容交互 configuration.userContentController = WKUserContentController() //注册js接ios中公用方法名称 configuration.userContentController.add(self, name: openAppMenu) configuration.userContentController.add(self, name: openAppLogin) configuration.userContentController.add(self, name: openAppPay) //configuration.userContentController.removeAllScriptMessageHandlers()- 移出所有注册方法 //configuration.userContentController.removeScriptMessageHandler(forName: openAppMenu)-移出单个方法 实现WKScriptMessageHandler协议,通过代理方法接收,并解析 func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { //print("name========\(message.name)") //print("body=======\(message.body)") /** 1.JS传值首先需要约定,然后注册 调用的方法名称: ->configuration.userContentController.add(self, name: openAppMenu) 2.如果交互 ,没有任何参数的情况, JS传递必须传递一个null,如果不传递任何参数, IOS这边回调方法不会执行 3. 传递参数智能是一个, 多个参数,也只会读取第一个参数,建议使用集合来传递参数 */ if message.name == openAppMenu { let cp_id = message.body as! Int let detaileVC = GYLP_Utils.getControllerToStroyBoard("HomeMian", "home_ZNCPDetail") as! GYZNCP_DetailViewController detaileVC.currentCP_ID = cp_id GYLP_Utils.getCurrentController().navigationController?.pushViewController(detaileVC, animated: true) } else if message.name == openAppLogin { //登录 let loginVC = GYLP_Utils.getControllerToStroyBoard("Main", "login") GYLP_Utils.getCurrentController().navigationController?.pushViewController(loginVC, animated: true) } else if message.name == openAppPay { //支付 let order_id = (message.body as! String).components(separatedBy: ",").first! let payType = Int((message.body as! String).components(separatedBy: ",").last!)! if payType == 0 { AlipaySDK.defaultService()?.payOrder(order_id, fromScheme: "zhongxiang", callback: { (resultDic) in print("orderPay========\(resultDic)") }) } else { //代表微信 } } }

3.3 在网页加载之前,传递值给H5

app需要写的代码: let param = ["uid":GYUserInfo.user_uid()!, "token":GYUserInfo.user_token()!] let data = try? JSONSerialization.data(withJSONObject: param, options: JSONSerialization.WritingOptions.prettyPrinted) let jsonString = String.init(data: data!, encoding: String.Encoding.utf8) let js = "userInfo = \(jsonString!)" let script = WKUserScript.init(source: js, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: true) configuration.userContentController.addUserScript(script) H5 接收 mounted(){ let iOSInfo = JSON.parse(JSON.stringify(window.iOSInfo)); // iOSInfo. username iOSInfo. token iOSInfo.avatar }
最新回复(0)