WKWebView是苹果在iOS8新引进的框架,在做WKWebView的js交互的时候:
一、WKWebView调用JS
使用WKWebView的evaluateJavaScript 方法:举个例子如果js中有个name 方法
调用js方法很简单只要
webView.evaluateJavaScript("name1()"){ (result,error)
}
调用后会有闭包返回。
二、用JS调用WKWebView
首先需要在原生端做一些准备,在初始化WKWebView的时候要添加如下代码配置
let webConfiguration = WKWebViewConfiguration() //用于初始化Web视图的属性集合
let pref = WKPreferences() //WKPreferences对象封装用于web视图偏好设置。
pref.javaScriptEnabled = true
webConfiguration.preferences = pref
webConfiguration.userContentController = WKUserContentController()
//对象提供了JavaScript来和注入用户脚本到web视图的方式
webConfiguration.userContentController.add(self, name:"appModel")
此时必须遵守WKScriptMessageHandler协议,WKScriptMessageHandler协议有一个
func userContentController(_ userContentController: WKUserContentController, didReceive message:WKScriptMessage) {
}方法,这个方法就是js端调用WKWebView时的返回结果。如下就是js端调用代码。
window.webkit.messageHandlers.appModel.postMessage(msg);
以上就可以做到js和原生交互的目的。问题1
内存泄露,只要在vc的deinit方法里面添加
webView.configuration.userContentController.removeAllUserScripts()就可以了。
问题2
有的时候会发现WKWebView的页面字体会比webview的小。这是因为html中少meta的配置。
一种解决方法是让写h5页面的同事添加在head里面添加
name="viewport"content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no,minimal-ui">
因为在我把webview 替换WKWebView的时候项目已经运行很长时间了,有一些网页有此字段,有一些没有。所以我就在WKWebView中自己注入了一个js方法
WKUserScript类可以注入js方法
WKUserScript的初始化方法 需要3个参数第一个是js脚本的源代码,脚本应该被注入到网页的时间,最后一个是一个布尔值,指示脚本是只应该注入到主框架(true
)还是注入到所有框架(false
)中。
注入如下js脚本源代码
let jsSource = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no'); document.getElementsByTagName('head')[0].appendChild(meta);"
//js脚本的源代码
let source = WKUserScript(source:jsSource, injectionTime:
WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: false)
注入时间最好在加载之后,因为不知道html 是不是有这个字段,应该以咱们添加的js为准。
webConfiguration.userContentController.addUserScript(source)
因为webView和WKWebView的js交互方式不一样,这样会导致js端也会跟着改动,这样很不好,考虑了一段时间怎么样才可以js端代码不用改动。如下是我想到的方法。
在WKWebView注入一段js代码,让js端调用方法和以前一样就可以了。举个例子:
以前webView的时候js交互用的是JSContext,注入一个对象,和一个方法,这样在js端就一个直接用这个对象的方法了,假如以前注入的对象是app,方法是jsFunc(str:String) ,只要我注入一段
var app = {
jsFunc : function(json)
{
window.webkit.messageHandlers.appModel.postMessage(json);
}
};
WKUserScript(source: js源代码(上面的), injectionTime:
WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false)