在Swift中加载HTML网页有两个view,分别是WKWebView和UIWebView,这里我使用的是WKWebView
这里分享一下我的写法:
1、定义变量WKWebView:
lazy var webView: WKWebView = {
///偏好设置
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
let configuration = WKWebViewConfiguration()
configuration.preferences = preferences
configuration.selectionGranularity = WKSelectionGranularity.character
configuration.userContentController = WKUserContentController()
// 给webview与swift交互起名字,webview给swift发消息的时候会用到
configuration.userContentController.add(WeakScriptMessageDelegate(self), name: "logger")
configuration.userContentController.add(WeakScriptMessageDelegate(self), name: "myPosition")
configuration.userContentController.add(WeakScriptMessageDelegate(self), name: "getRegistionId")
configuration.userContentController.add(WeakScriptMessageDelegate(self), name: "getUserInfo")
configuration.userContentController.add(WeakScriptMessageDelegate(self), name: "saveUserInfo")
configuration.userContentController.add(WeakScriptMessageDelegate(self), name: "scanCode")
configuration.userContentController.add(WeakScriptMessageDelegate(self), name: "alertl")
var webView = WKWebView(frame: CGRect(x: 0,
y: 44,
width: UIScreen.main.bounds.width,
height: UIScreen.main.bounds.height-20),
configuration: configuration)
// 让webview翻动有回弹效果
webView.scrollView.bounces = false
// 只允许webview上下滚动
webView.scrollView.alwaysBounceVertical = true
webView.navigationDelegate = self
//自定义userAgent,用于在浏览器中判断是否在app打开
webView.customUserAgent = "iosApp"
return webView
}()
注意,此加载网页的视图控制器需要实现这两个协议:WKNavigationDelegate,WKScriptMessageHandler
注:这里说明一下这行代码:configuration.userContentController.add(WeakScriptMessageDelegate(self), name: "logger")
configuration在上面代码区域可以看到,是定义的一个WKWebViewConfiguration() ,
然后调用它的userContentController.add() ,这里简单说明一下参数:第一个参数位置WeakScriptMessageDelegate协议,这里是固定写法,
主要看第二个参数name,name的值需要注意,它是一个字符串,就是我们在js中需要通过这个name,然后点上swift中原生的方法完成交互功能,js中所有需要需要调用swift原生方法的语句,都需要在swift中定义一个对月的name,
下面介绍如何在swift中处理js调用原生方法时判断调用的是哪一个方法,判断方法也是通过上面定义的name去区分,可以携带参数:
要重写下面的这个函数:userContentController ,注意参数
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
///接收js调用方法
///在控制台中打印html中console.log的内容,方便调试
let body = message.body
print("--------js交互了------------")
if message.name == "logger" {
print("JS Log \(body)")
EWToast.showBottomWithText(text: "JS Log: \(body)")
return
}
///message.name是约定好的方法名,message.body是携带的参数
switch message.name {
case "myPosition":
///不接收参数时直接不处理message.body即可,不用管Html传了什么
self.myDistance()
case "getRegistionId":
self.getRegistId()
case "getUserInfo":
self.getUserInfo()
case "saveUserInfo":
self.saveInfo(array: message.body as! [AnyObject])
case "scanCode":
// 打开相机
self.openCemera()
case "alertl":
//这个项目中单独的Toast提示
EWToast.showBottomWithText(text: "触发成功")
default:
break
}
}
仔细一看,每一个case 判断的字符串就是上面我们定义的name,在js中调用时,它会自动根据你调用原生方法时用的是哪一个,他就会走对应的判断,然后在case中我们就可以调用原生的方法了,
在js向原生传递参数时,可以传递数组,这里我用的是数组传递,没看到单个数据怎么传递的,
写法:window.webkit.messageHandlers.saveUserInfo.postMessage(["abcd",1])
注意代码标红的就是我们在swift中定义的name,后面的postMessage这个随意,看你想做什么用就写什么,没什么特殊要求,这里是传递消息,主要是参数,我用数组,传递不一样的数据类型也可以,
在swift中接收参数可以看到 我是这么写的:self.saveInfos(array: message.body as! [AnyObject])
这样就可以了!去试试吧!
在多说一句:原生调用js方法:
webView.evaluateJavaScript("setToken('\(token ?? "")')", completionHandler: nil)
setToken是js提供的function函数如:
function setToken(token){
//操作
}