根据实际使用遇到的问题分成3个部分
- 加载本地html文件
- h5和iOS原生交互
- WKWebview中post请求总是失败的问题
加载本地html文件
代码
guard let directorPath = Bundle.main.path(forResource: "dist", ofType: nil),
let h5Bundle = Bundle(path: directorPath),
let h5Path = h5Bundle.path(forResource: "index", ofType: "html"),
let path = h5Path.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed),
let url = URL(string: "file://"+path)
else{
alert(title: "严重错误", message: "无法加载h5")
return
}
let request = URLRequest(url: url)
webview.load(request)
首先在mainBundle中去找dist文件夹
得到这个路径后,将dist作为一个Bundle加载
在dist中去找index.html文件
预防遇到编码问题用了addingPercentEncoding方法
因为是本地文件,所以路径前需要加上file://
文件引入方式
注意dist文件夹加入的方式,可以整个文件夹放进本项目中,也可以不放在本项目中。引入使用folder references
引入项目.jpg
对应target设置
设置.jpg
将文件夹作为folder references引入,这样,引入文件只有这一个,不会让其内部的js,css,ttf,html等都被加进来,导致Copy Bundle Resources中引入过多文件
h5和iOS原生交互
WKWebview和js通过WKScriptMessageHandler协议交互
iOS中代码
let msgHandlerName = "ANY_WORD"
添加
viewDidLoad中
让self(ViewController)可以处理msgHandlerName这个名字的消息
前提:ViewController必须遵守协议WKScriptMessageHandler
webview.configuration.userContentController.add(self, name: msgHandlerName)
移除
deinit中
webview.configuration.userContentController.removeScriptMessageHandler(forName: msgHandlerName)
遵守协议
可以根据功能分类,定义多个name,分别处理
这里body规则,需要和h5统一规定,我这里的规则是,将方法名和参数通过逗号隔开,连成一整个字符串
extension ViewController: WKScriptMessageHandler{
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
guard message.name == msgHandlerName else{
return
}
if let msgBody = message.body as? String{
switch (msgBody){
case "takePhoto":
takePhoto()
case let x where x.hasPrefix("callSb"):
let arr = x.split(separator: ",")
if arr.count>1{
let phoneNum = String(arr[1])
callSb(phoneNum)
}else{
toast("没有接收到电话号码")
}
default:
alert(title: "调用原生功能失败", message: "iOS中没有定义\(msgBody)方法")
break
}
}
}
}
js 调用iOS原生(js代码)
if (isAndroid()) {
window.android.takePhoto();
} else {
window.webkit.messageHandlers.ANY_WORD.postMessage("takePhoto");
}
js就是通过 window.webkit.messageHandlers. msgHandlerName.postMessage("方法名,参数1,参数2")
的格式调用iOS原生方法
msgHandlerName为开始在iOS中add的messageHandlerName
iOS调用js方法(iOS代码)
let callJS="callJSMethod(1)"
self.webview.evaluateJavaScript(callJS)
其中callJSMethod必须为js中已经定义的方法
定义方式可以是在js源码中,也可以是之前通过evaluateJavaScrip方法定义的js方法
tip: evaluateJavaScrip方法可以在js方法执行完后调用iOS中的completionHandler
callJS.jpg
WKWebview中post请求总是失败的问题
WKWebview中h5发送post请求失败是当前WKWebview本身不支持的问题
解决方案:使用了第三方库IMYWebLoader
查了github上一些库,觉得这个第三方库最合我思路,使用方式也简单
- 通过pod添加这个库
pod 'IMYWebLoader'
- 因为这个库是OC实现的,所以需要添加swift和OC桥接
在桥接的.h文件中引入这个库
#import <IMYWebLoader/IMYWebLoader.h>
就能在Swift中使用OC代码了
- 在代码中引入
webview.configuration.userContentController.imy_installHookAjax()
网友评论