原生运用中或多或少都会接入H5界面,运用WKWebView加载,这就避免不了native与H5交互了。
传统交互方案:
直接体系体系API。
长处:简略 缺陷:重复处理阻拦事情
举例:
想在H5加载之前就传递给H5一些参数信息,能够这么干:
// 初始化WKWebView时候,直接传递给H5一点参数。 这儿以传给它平台信息为例。
let configuration = WKWebViewConfiguration()
configuration.applicationNameForUserAgent = "iOS"
let script = WKUserScript(source: "window.platform = 'iOS'", injectionTime: .atDocumentStart, forMainFrameOnly: true)
configuration.userContentController.addUserScript(script)
如果在加载界面后传递,运用evaluateJavaScript
办法即可:
// 这儿也能够添加参数
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
办法里监听对应的事情即可:
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
switch message.name {
case "MessageHandle":
print("处理H5数据")
default: break
}
}
以上是运用体系API,基础通讯啦。可是这样,有多个事情,就要传多少次,很麻烦。 想这只监听一个办法,就能阻拦一切的交互事情呢?已经有了现成轮子,Swift运用WKWebViewJavascriptBridge
。 WKWebViewJavascriptBridge
依照步骤,只需两步,就可完成接入。
1、确保Bridge初始化前已经有了webView!!!
bridge = WKWebViewJavascriptBridge(webView: webView)
2、注册事情:
只需一致注册一个事情
JS_CALL_APP_FUN
来监听即可。
- // JS主动调用native的办法
- // 这是JS会调用JS_CALL_APP_FUN办法,这是native注册给JS调用的
- // JS需求回调,当然JS也能够传参数过来。data便是JS所传的参数,不一定需求传=
- // native端通过responseCallback回调JS端,JS就能够得到所需求的数据
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.
jsBridge.callHandler:"APP_CALL_JS_FUN" data:@"传递给 JS 的参数") { responseData in
}
具体后续办法名啊、参数啊, 就与JS与约定好了。这样就能一致处理了。 不想写了,直接上我的部分代码自己看看吧。
恳求传参:
{
'operate':'callPhone',
'data':{
'phone':'18888888888'//手机号码,必须
}
}
回来给JS数据:
{
'msg':'',//success或许为其他Native或许传给H5的错误提示信息
'code':0,//0 代表Native解析成功
'data':{
'token':'fewifhwiuhfuiewhf'
}
}
一致阻拦处理办法:
先界说传递以及恳求的Model:
/// 与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:
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)")
}
}
}
算了先这样吧,看不懂的再来。。