Sop*_*ert 46 javascript webkit ios wkwebview
在iOS 8中使用WKWebView,如何从本机端运行JavaScript函数或以其他方式从本机端到JavaScript进行通信?似乎没有类似于UIWebView的方法stringByEvaluatingJavaScriptFromString:.
(我可以- addScriptMessageHandler:name:在configuration.userContentController对象上使用以允许从JS到本地的通信,但我正在寻找相反的方向.)
Sop*_*ert 60
(我在这里提出这个问题之后不久就提交了雷达.)
几天前刚刚添加了一种新方法(感谢jcesarmobile指出它):
添加
-[WKWebView evaluateJavaScript:completionHandler:]
http://trac.webkit.org/changeset/169765
该方法适用于iOS 8 beta 3及更高版本.这是新方法签名:
/* @abstract Evaluates the given JavaScript string.
@param javaScriptString The JavaScript string to evaluate.
@param completionHandler A block to invoke when script evaluation completes
or fails.
@discussion The completionHandler is passed the result of the script evaluation
or an error.
*/
- (void)evaluateJavaScript:(NSString *)javaScriptString
completionHandler:(void (^)(id, NSError *))completionHandler;
Run Code Online (Sandbox Code Playgroud)
文档可在此处获取:https://developer.apple.com/documentation/webkit/wkwebview/1415017-evaluatejavascript.
Vas*_*huk 22
Xcode 9.1,Swift 4
该脚本将插入到将在WKWebView中显示的页面中.此脚本将返回页面URL(但您可以编写另一个JavaScript代码).这意味着脚本事件是在网页上生成的,但它将在我们的函数中处理:
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {...}
Run Code Online (Sandbox Code Playgroud)
extension WKUserScript {
enum Defined: String {
case getUrlAtDocumentStartScript = "GetUrlAtDocumentStart"
case getUrlAtDocumentEndScript = "GetUrlAtDocumentEnd"
var name: String { return rawValue }
private var injectionTime: WKUserScriptInjectionTime {
switch self {
case .getUrlAtDocumentStartScript: return .atDocumentStart
case .getUrlAtDocumentEndScript: return .atDocumentEnd
}
}
private var forMainFrameOnly: Bool {
switch self {
case .getUrlAtDocumentStartScript: return false
case .getUrlAtDocumentEndScript: return false
}
}
private var source: String {
switch self {
case .getUrlAtDocumentEndScript, .getUrlAtDocumentStartScript:
return "webkit.messageHandlers.\(name).postMessage(document.URL)"
}
}
fileprivate func create() -> WKUserScript {
return WKUserScript(source: source,
injectionTime: injectionTime,
forMainFrameOnly: forMainFrameOnly)
}
}
}
extension WKWebViewConfiguration {
func add(script: WKUserScript.Defined, scriptMessageHandler: WKScriptMessageHandler) {
userContentController.addUserScript(script.create())
userContentController.add(scriptMessageHandler, name: script.name)
}
}
Run Code Online (Sandbox Code Playgroud)
初始化WKWebView
let config = WKWebViewConfiguration()
config.add(script: .getUrlAtDocumentStartScript, scriptMessageHandler: self)
config.add(script: .getUrlAtDocumentEndScript, scriptMessageHandler: self)
webView = WKWebView(frame: UIScreen.main.bounds, configuration: config)
webView.navigationDelegate = self
view.addSubview(webView)
Run Code Online (Sandbox Code Playgroud)
抓住事件
extension ViewController: WKScriptMessageHandler {
func userContentController (_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if let script = WKUserScript.Defined(rawValue: message.name),
let url = message.webView?.url {
switch script {
case .getUrlAtDocumentStartScript: print("start: \(url)")
case .getUrlAtDocumentEndScript: print("end: \(url)")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
private var webView = WKWebView()
override func viewDidLoad() {
super.viewDidLoad()
let config = WKWebViewConfiguration()
config.add(script: .getUrlAtDocumentStartScript, scriptMessageHandler: self)
config.add(script: .getUrlAtDocumentEndScript, scriptMessageHandler: self)
webView = WKWebView(frame: UIScreen.main.bounds, configuration: config)
webView.navigationDelegate = self
view.addSubview(webView)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
webView.load(urlString: "http://apple.com")
}
}
extension ViewController: WKScriptMessageHandler {
func userContentController (_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if let script = WKUserScript.Defined(rawValue: message.name),
let url = message.webView?.url {
switch script {
case .getUrlAtDocumentStartScript: print("start: \(url)")
case .getUrlAtDocumentEndScript: print("end: \(url)")
}
}
}
}
extension WKWebView {
func load(urlString: String) {
if let url = URL(string: urlString) {
load(URLRequest(url: url))
}
}
}
extension WKUserScript {
enum Defined: String {
case getUrlAtDocumentStartScript = "GetUrlAtDocumentStart"
case getUrlAtDocumentEndScript = "GetUrlAtDocumentEnd"
var name: String { return rawValue }
private var injectionTime: WKUserScriptInjectionTime {
switch self {
case .getUrlAtDocumentStartScript: return .atDocumentStart
case .getUrlAtDocumentEndScript: return .atDocumentEnd
}
}
private var forMainFrameOnly: Bool {
switch self {
case .getUrlAtDocumentStartScript: return false
case .getUrlAtDocumentEndScript: return false
}
}
private var source: String {
switch self {
case .getUrlAtDocumentEndScript, .getUrlAtDocumentStartScript:
return "webkit.messageHandlers.\(name).postMessage(document.URL)"
}
}
fileprivate func create() -> WKUserScript {
return WKUserScript(source: source,
injectionTime: injectionTime,
forMainFrameOnly: forMainFrameOnly)
}
}
}
extension WKWebViewConfiguration {
func add(script: WKUserScript.Defined, scriptMessageHandler: WKScriptMessageHandler) {
userContentController.addUserScript(script.create())
userContentController.add(scriptMessageHandler, name: script.name)
}
}
Run Code Online (Sandbox Code Playgroud)
添加Info.plist传输安全设置
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Run Code Online (Sandbox Code Playgroud)
小智 5
它可能不是一种理想的方法,但根据您的用例,您可以在感染用户脚本后重新加载WKWebView:
NSString *scriptSource = @"alert('WKWebView JS Call!')";
WKUserScript *userScript = [[WKUserScript alloc] initWithSource:scriptSource
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
forMainFrameOnly:YES];
[wkWebView.configuration.userContentController addUserScript:userScript];
[wkWebView reload];
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
52985 次 |
| 最近记录: |