WKWebView与H5、UniApp交互方案-纯小白看

原生应用中或多或少都会接入H5界面,使用WKWebView加载,这就避免不了native与H5交互了。

传统交互方案:

直接系统系统API。 优点:简单 缺点:重复处理拦截事件 举例: 想在H5加载之前就传递给H5一些参数信息,可以这么干:

ini 复制代码
        // 初始化WKWebView时候,直接传递给H5一点参数。  这里以传给它平台信息为例。
        let configuration = WKWebViewConfiguration()
        configuration.applicationNameForUserAgent = "iOS"
        let script = WKUserScript(source: "window.platform = 'iOS'", injectionTime: .atDocumentStart, forMainFrameOnly: true)
        configuration.userContentController.addUserScript(script)

如果在加载界面后传递,使用evaluateJavaScript方法即可:

csharp 复制代码
    // 这里也可以添加参数
        let script = "window.webkit.messageHandlers.messageHandler.postMessage('Hello, H5!',{
          resolution: "\#(resolution)",
          chartType: \#(chartType)
        })"
        webView.evaluateJavaScript(script, completionHandler: nil)

添加交互事件: configuration.userContentController.add(self, name: "MessageHandle") 然后再代理WKScriptMessageHandler方法里监听对应的事件即可:

swift 复制代码
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        switch message.name {
            case "MessageHandle": 
                print("处理H5数据")
            default: break
        }
    }

以上是使用系统API,基础通信啦。但是这样,有多个事件,就要传多少次,很麻烦。 想这只监听一个方法,就能拦截所有的交互事件呢?已经有了现成轮子,Swift使用WKWebViewJavascriptBridgeWKWebViewJavascriptBridge

按照步骤,只需两步,就可完成接入。

1、确保Bridge初始化前已经有了webView!!! bridge = WKWebViewJavascriptBridge(webView: webView) 2、注册事件:

只需统一注册一个事件JS_CALL_APP_FUN来监听即可。

  1. // JS主动调用native的方法
  2. // 这是JS会调用JS_CALL_APP_FUN方法,这是native注册给JS调用的
  3. // JS需要回调,当然JS也可以传参数过来。data就是JS所传的参数,不一定需要传=
  4. // native端通过responseCallback回调JS端,JS就可以得到所需要的数据
less 复制代码
        jsBridge.register(handlerName: "JS_CALL_APP_FUN", handler: { parameters, responseCallBack in
            // 解析处理JS调OC的事件,然后将结果callback返回给他
            JSWebManager.appResponeJsCallBack(params: parameters, callBack: responseCallBack)
        })

native 调用JS方法。 也只注册一个事件APP_CALL_JS_FUN. 具体什么事件、以及参数,在data里传给JS.

css 复制代码
jsBridge.callHandler:"APP_CALL_JS_FUN" data:@"传递给 JS 的参数") { responseData in

        }

具体后续方法名啊、参数啊, 就与JS与约定好了。这样就能统一处理了。 不想写了,直接上我的部分代码自己看看吧。 请求传参:

ruby 复制代码
{
'operate':'callPhone',
'data':{
        'phone':'18888888888'//手机号码,必须
    }
}

返回给JS数据:

csharp 复制代码
{

'msg':'',//success或者为其他Native可能传给H5的错误提示信息
'code':0,//0 代表Native解析成功
'data':{
        'token':'fewifhwiuhfuiewhf'
    }
}

统一拦截处理方法:

先定义传递以及请求的Model:

less 复制代码
/// 与H5交互,H5调用OC的方法传过来的Model

struct ExWebRequestModel<T: Codable>: Codable {
    var operate: String = ""// 具体方法名称
    var data: T
}

// data里单个参数的

struct ExWebRequestCommonModel: Codable {
    var params: String?
    var token: String?
    ...
}

struct ExWebRequestParamModel: Codable {
    var params: ExWebParamsModel?
    var path: String?
    ...
}

/// 如果有带额外参数,放在这里

struct ExWebParamsModel: Codable {
    var isbn: String?
    var studentId: String?
    ...
}

  


  


/// OC处理完成后返回给H5返回的Model
struct ExWebResponseModel: Codable {
    var code: Int = 0
    var msg: String = "sucess"
    var data: ExWebResponDetailModel?
}

// 所有的返回数据都放在一个Model里,要哪个给哪个就行
struct ExamWebResponDetailModel: Codable {
    var client: String?
    var version: String?
    var model: String? //手机型号
    var appVersionName: String?
    var appVersionCode: String? //版本号
    var manufacturer: String? //手机厂商
    var debug: Bool?
    var name: String?
    var userType: String?
    var status: Int?
    ...
}

统一拦截处理Manager:

php 复制代码
static func appResponeJsCallBack(params: [String: Any]?, callBack: ((_ responseData: Any?) -> Void)?) {
        guard let paramsDict = params else { return }
        guard let operate = paramsDict["operate"] else { return }
        

        let operateType = JSCallAppFuncName(rawValue: operate as! String)
        switch operateType {
            // 这个优点特殊,单独处理
            case .openPage:
                do {
                    let jsonData = try JSONSerialization.data(withJSONObject: paramsDict, options: .prettyPrinted)
                    let paramsModel = try App.shared.decoder.decode(ExWebRequestModel<ExWebRequestParamModel>.self, from: jsonData)
                    // 处理具体的JS调OC事件
                    operateJsCallFunc(commonModel: ExWebRequestCommonModel(), paramsModel: paramsModel.data, operate: operateType ?? .none, callBack: callBack)
                } catch {
                    print("Error: \(error)")
                }
            default:
                do {
                    let jsonData = try JSONSerialization.data(withJSONObject: paramsDict, options: .prettyPrinted)
                    // 处理 data

                    //            let jsonString = String(data: jsonData, encoding: .utf8)
                    let model = try App.shared.decoder.decode(ExWebRequestModel<ExWebRequestCommonModel>.self, from: jsonData)
                    print(model.operate)
                    // 处理具体的JS调OC事件
                    operateJsCallFunc(commonModel: model.data, paramsModel: ExamWebRequestParamModel(), operate: operateType ?? .none, callBack: callBack)
                } catch {
                    print("Error: \(error)")
                }
        }
    }

    

    /// 解析JS掉用的哪个方法
    static func operateJsCallFunc(commonModel: ExWebRequestCommonModel, paramsModel: ExWebRequestParamModel, operate: JSCallAppFuncName, callBack: ((_ responseData: Any?) -> Void)?) {
        switch operate {
            case .getClientInfo:
                // 对应事件处理完成后,返回数据给JS
                let model = ExWebResponseModel(data: ExamWebResponDetailModel(client: "iOS", version: Env.osVersion, model: UIDevice.current.type.rawValue, appVersionName: Env.appName, appVersionCode: Env.bundleShortVersion, manufacturer: "iPhone", debug: Env.isDebug))
                jsCallFuncCallback(model: model, callBack: callBack)
            case .openPage:
                let paramsModel = paramsModel.path
                //  拿到参数知道干啥事哈

                

                // 回参数给JS
                let model = ExamWebResponseModel()
                jsCallFuncCallback(model: model, callBack: callBack)
            case .getUserInfo:
                let model = ExamWebResponseModel(data: ExamWebResponDetailModel(name: "小红", userType: "iOS客户端"))

                jsCallFuncCallback(model: model, callBack: callBack)
                ...

            default:
                break
        }
    }
    

    

    /// JS调用完成给它的回调信息- 具体哪个Model不同而已
    static func jsCallFuncCallback(model: ExWebResponseModel, callBack: ((_ responseData: Any?) -> Void)?) {
        do {
            let jsonData = try App.shared.encoder.encode(model)
            let jsonString = String(data: jsonData, encoding: .utf8)
            callBack?(jsonString)
        } catch {
            print("Error: \(error)")
        }
    }
}

算了先这样吧,看不懂的再来。。

相关推荐
hxx2211 天前
iOS swift开发--- 加载PDF文件并显示内容
ios·pdf·swift
今天也想MK代码2 天前
基于ModelScope打造本地AI模型加速下载方案
ai·语言模型·swift·model·language model
袁代码2 天前
Swift 开发教程系列 - 第11章:内存管理和 ARC(Automatic Reference Counting)
开发语言·ios·swift·ios开发
袁代码3 天前
Swift 开发教程系列 - 第8章:协议与扩展
开发语言·ios·swift·ios开发
袁代码3 天前
Swift 开发教程系列 - 第9章:错误处理
开发语言·ios·swift·ios开发
iFlyCai3 天前
Swift中的Combine
开发语言·ios·swift·combine·swift combine
一丝晨光3 天前
Objective-C 1.0和2.0有什么区别?
java·开发语言·macos·c#·objective-c·swift·apple
新中地GIS开发老师4 天前
【GIS开发小课堂】高德地图+Three.js实现飞线、运动边界和炫酷标牌
开发语言·javascript·arcgis·前端框架·swift
袁代码4 天前
Swift 开发教程系列 - 第10章:泛型
开发语言·ios·swift·ios开发
袁代码4 天前
Swift 开发教程系列 - 第12章:协议与协议扩展
开发语言·ios·swift·ios开发