分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 代码编程

webview和H5交互

发布时间:2023-09-06 02:23责任编辑:熊小新关键词:webview

由于H5的灵活多变,动态可配的特点,也为了避免冗长 的审核周期,H5页面在app上的重要性正日益突显。

iOS应用于H5交互的控件主要是UIWebView及WKWebView

WKWebView是14年随iOS8推出的,很好的解决了UIWebView加载速度慢,内存占用大的问题

WebViewJavaScriptBridge是一款轻量级的框架,使用它结合wkwebview能十分方便的实现源生与H5的交互

  webviewJavaScrptBridge的基本使用

  1.初始化需bind视图  [WebViewJavaScriptBridge bridgeForWebView:]

  2.设置代理  [self.bridge setWebViewDelegate:self]

  3.注册方法  

  [self.bridge registerHandler:@"click" handler:^(id data, WVJBResponseCallback responseCallback) {

        NSDictionary *dic = (NSDictionary *)data;

        [weakSelf responseJSWithData:(NSDictionary *)dic];

     }];

  click是方法名,handler是H5发起调用后传回的回调,该闭包第一个H5页面传递过来的参数,第二个是callBack对象

  4.调用方法  

  [self.bridge callHandler:event data:data responseCallback:^(id responseData) {

        NSLog(@"responseData:%@",responseData);

     }];

  event是方法名,源生直接发起回调,data是传递的参数,callBack是h5收到事件后传回的回调

  webviewJavaScriptBridge的精髓就是方法3,4的交替使用,使得源生调h5,h5调源生变的异常简单,两者之间的链接仅仅靠一个方法名,收方register后,发起方callHandler就能实现一条消息的有效传递,具体实现细节可细究其源码  webviewJavaScriptBridge

  现在来探究下H5端如何使用bridge注册及发起事件

/// 配置bridgefunction 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) ???}/// callHandler ???data为H5传递参数setupWebViewJavascriptBridge(function (bridge) { ???????????let data = {‘title‘: title} ???????????bridge.callHandler(‘setTitle‘, data) ???????})/// registerHandler ???data为源生传递参数bridge.registerHandler("result", function (data, responseCallback) { ???????????result(data[‘opType‘], data[‘code‘], data[‘msg‘]) ???????})

   可见在H5端使用bridge完成消息的收发页十分方便。webviewJavaScriptCoreBridge的配置,是在H5页面生成一个iframe节点,传递消息时插入这个节点,结束后移除这个节点,以此来实现源生到H5的一次消息传递。

WKNavigationDelegate  使用wkwebview进行一次网络请求中的各种事件回调

WKUIDelegate   主要用于处理H5中的alert弹窗事件

  -runJavaScriptAlertPanelWithMessage:

UIWebView,尽管该视图已经被WKWebview取代,但市面上大多数应用框架仍然使用的是webview,并且其更接近底层,具有深究价值

UIWebview通常是通过拦截request,根据指定url中的参数,来实现H5端事件的调用

func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool ???{ ???????let ?absoluteString = request.url!.absoluteStringif (!absoluteString.contain(prefix)) {return true}else {
              // do somethingreturn false} ???}

返回false则拦截请求,截取url中所带参数,根据需求做相应处理。通常为封装方法间的调用,会插入一段js代码。

override func webViewDidStartLoad(_ webView: UIWebView) { ???????super.webViewDidStartLoad(webView) ???????????????/// 尽可能在较早的时间点插入该js代码 ???????writtenJSApi(webView: webView) ???}func writtenJSApi(webView:UIWebView) { ???????if ?let filePath:String = Bundle.main.path(forResource: "jsapi", ofType: "js"){ ???????????if let jsStr = try? NSString(contentsOfFile: filePath, encoding: String.Encoding.utf8.rawValue){ ???????????????webView.stringByEvaluatingJavaScript(from: jsStr as String) ???????????} ???????} ???}

 js主要代码

// 异步 window.JSApi.asyncInvoke = function (apiname, pramaJsonString, callbackapi) { var apiPath = "https://asyncjsapi.com/" + encodeURIComponent(apiname + window.JSApi.pramaSplit + pramaJsonString + window.JSApi.pramaSplit + callbackapi); var iframe = document.createElement("iframe"); iframe.setAttribute("src", apiPath); document.documentElement.appendChild(iframe); iframe.parentNode.removeChild(iframe); iframe = null; } ?// 同步 window.JSApi.syncInvoke = function (apiname, pramaJsonString) { var apiPath = "https://syncjsapi.com/" + encodeURIComponent(apiname + window.JSApi.pramaSplit + pramaJsonString ); var request = new XMLHttpRequest(); if (request == null) { return { code: 1, errorMsg: "not support XMLHttpRequest", data: null }; } ?var responseText = "" ?request.onreadystatechange = function () { // alert("stateChange"+request.readyState+","+request.status) if (request.readyState == 4 && request.status == 200) { responseText = request.responseText; } else { responseText = "" } // alert(responseText) }; // alert(apiname+" ?2 ?request open ???"+apiPath); request.open("GET", apiPath, false); request.send(null); ?console.log(responseText) ?return responseText } })();

 可以看出,异步方法依然是在页面创建iframe,先插入后删除的方式;同步方法是利用ajax,创建了一个http请求,并监听request的状态,当status为200时,返回信息给H5。同步方法的拦截是在urlProtocol里面

class JsApiURLProtocol: URLProtocol, URLSessionDataDelegate, URLSessionTaskDelegate {override class func canInit(with request: URLRequest) -> Bool {if let strUrl:String = request.url?.absoluteString ???????{ ???????????if JsApiHelper.isSyncNativeApi(urlString: strUrl) { ???????????????return true ???????????} ???????}else { ???????return false ???????}}override func startLoading() { ???????let strUrl:String! = request.url!.absoluteString ???????if JsApiHelper.isSyncNativeApi(urlString: strUrl) { ???????????// 调用同步jsapi ???????????let result: NSString = JsApiHelper.syncInvoke(urlString: strUrl! as NSString) as NSString ???????????let resultData: NSData = result.data(using: String.Encoding.utf8.rawValue)! as NSData ???????????var headerFields: [NSObject : AnyObject]? = [NSObject : AnyObject]() ???????????headerFields?.updateValue("*" as AnyObject, forKey: "Access-Control-Allow-Origin" as NSObject) ???????????????????????let response: HTTPURLResponse = HTTPURLResponse(url: self.request.url!, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: headerFields as? [String:String])! ???????????self.client!.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed) ???????????self.client!.urlProtocol(self, didLoad: resultData as Data) ???????????self.client!.urlProtocolDidFinishLoading(self) ???????} ???}}

 caninit方法中return true表示进行请求,否则拦截请求。startLoading方法中创建相应的response返回给js中的request,注意finishLoading,否则容易造成死循环。

UIWebview调用H5就相当简单了,一句代码搞定

  webView.stringByEvaluatingJavaScript(from: "javascript:window.goBack()");

webview和H5交互

原文地址:https://www.cnblogs.com/xiaoerheiwatu/p/10004409.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved