最近对接过公司的一个h5的东西,就是给一个入口,点击进wkWebView,其他的交给h5,简单说一下方法思路
第一 和h5共同商讨交互字段问题,定下来返回格式。然后使用wkwebView的configuration配置一下
let userContent = WKUserContentController()
self.userContent = userContent
userContent.add(JFToNative(), name: "JsToNative")
config.userContentController = userContent
let webView = CustomWKWebView(frame: view.bounds, configuration: config)
其中 userContent.add(JFToNative(), name: "JsToNative")
JFToNative() 就是实现 WKScriptMessageHandler 协议的 func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) () 方法
class JFToNative: NSObject, WKScriptMessageHandler {
weak var webView: WKWebView!
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
webView = message.webView
if let dict = message.body as? [String: Any] {
debugPrint(dict)
if let tempClass = dict["class"] as? String {
let method = dict["method"] as? String ?? ""
let json = JSON(dict["params"] as Any)
if tempClass == "xxx" {
//这里调用你的方法
}else if tempClass == "xxx" {
//这里调用你的方法
}
}
}
}
你也可以在当前类实现,直接self即可,但是我学习大佬同事的方式,把它分开写了,但是由于东施效颦,没学好(在第一步的时候和h5商定协议就有问题,大佬的方式是 window.webkit.messageHandlers.JsToNative.postMessage({'class' : 'NativeXxx', 'method' : 'xxx', 'params' : {'key0' : 'value0', 'key1' : 'value1', ...}}))
在桥接文件这么写
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
guard let dict = message.body as? [String : Any],
let cls = NSClassFromString(kNameSpace + "." + (dict["class"] as? String ?? "")) as? NativeBase.Type,
let method = dict["method"] as? String, !method.isEmpty else {return}
let obj = cls.init()
let sel = Selector(method + ":")
if obj.responds(to: sel) {
obj.webView = message.webView
var params = dict["params"] as? [String : Any]
if params?.count == 0 {
params = nil
}
obj.perform(sel, with: params)
}
}
他的class继承 NativeBase
class NativeBase: NSObject {
weak var webView: WKWebView?
override required init() {
super.init()
}
}
class就是你方法调用应该写的类名字,我们提供,method就是h5的回掉方法名字,params就是提供给我们的一些参数。
我商定的交互方式是class 是方法名,所以造成了无法像大佬这种用,不能继承他的基础webVC。只能拷贝他的webVC删除多余的方法。使用了重复的代码。
言归正传,我们给js发消息是通过evaluateJavaScript这个方法
open func evaluateJavaScript(_ javaScriptString: String) async throws -> Any
javaScriptString是一个字符串,一般和h5商定好,给他返回某种格式的json字符串。我们商定的是 如下格式
dic = ["code": "000000", "msg": msg]
if let data = try? JSONSerialization.data(withJSONObject: dic, options: .prettyPrinted) {
if let str = String(data: data, encoding: .utf8) {
let strs = str.jsonRemoveOther()
jsonRemoveOther是
///jsonstr移除其他特殊字符
func jsonRemoveOther() -> String {
var content = self.replacingOccurrences(of: "\\'", with: "\"")
content = content.replacingOccurrences(of: "\r", with: "")
content = content.replacingOccurrences(of: "\n", with: "")
content = content.replacingOccurrences(of: "\t", with: "")
content = content.replacingOccurrences(of: "\\", with: "")
return content
}
有些时候需要把iOS的特殊符号移除掉,不然h5解析不到,这方面我不是特别清楚,应该h5是可以处理的,但是具体看沟通吧。
其他问题,我们的h5 VC 导航栏是给h5自己设置的。出现一个问题,h5VC的滚动范围,可以滚动到状态栏去,但是这个听其他同事们说,之前接过的h5是都是让h5自己处理的,所以这个问题我让他们来处理,起始我自己的话,把view的y轴位置增加一个状态栏的高度,view 的height 减少一个h5的高度。但是这个页面其他地方也有用,所以有点害怕出问题。所以给h5处理了






网友评论