swift - 无法将 JS 注入 Swift/Cocoa/NextStep 中的 WKWebView / 将 WKWebView 中网页上的用户选择推送到 Swift / Cocoa
问题描述
我正在使用需要使用 WKUserScript 功能将消息从网页发送回 MacOS 应用程序的 MacOS 应用程序。我正在使用文章https://medium.com/capital-one-tech/javascript-manipulation-on-ios-using-webkit-2b1115e7e405,它显示了它在 iOS 中的工作并且工作得很好。
然而,我已经苦苦挣扎了几个星期,试图让它在我的 MacOS 中工作。这是我的代码示例,该代码可以正常运行并运行但未成功打印在处理程序 userContentController() 中找到的消息
import Cocoa
import WebKit
class ViewController: NSViewController, WKNavigationDelegate {
@IBOutlet weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let userContentController = WKUserContentController()
// Add script message handlers that, when run, will make the function
// window.webkit.messageHandlers.test.postMessage() available in all frames.
userContentController.add(self, name: "test")
// Inject JavaScript into the webpage. You can specify when your script will be injected and for
// which frames–all frames or the main frame only.
let scriptSource = "window.webkit.messageHandlers.test.postMessage(`Hello, world!`);"
let userScript = WKUserScript(source: scriptSource, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
userContentController.addUserScript(userScript)
// let config = WKWebViewConfiguration()
// config.userContentController = userContentController
// let webView = WKWebView(frame: .zero, configuration: config)
webView.navigationDelegate = self
webView.configuration.userContentController = userContentController
// Make sure in Info.plist you set `NSAllowsArbitraryLoads` to `YES` to load
// URLs with an HTTP connection. You can run a local server easily with services
// such as MAMP.
let htmlStr = "<html><body>Hello world - nojs</body></html>"
webView.loadHTMLString(htmlStr, baseURL: nil)
}
}
extension ViewController: WKScriptMessageHandler {
// Capture postMessage() calls inside loaded JavaScript from the webpage. Note that a Boolean
// will be parsed as a 0 for false and 1 for true in the message's body. See WebKit documentation:
// https://developer.apple.com/documentation/webkit/wkscriptmessage/1417901-body.
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if let messageBody = message.body as? String {
print(messageBody)
}
}
}
另一个奇怪的事情是,我似乎无法创建一个简单的 WKWebView 应用程序来加载页面并显示它。这些都只是简单的测试,我的主应用程序能够很好地加载/显示网页,使用 AlamoFire/loadHTMLString() 来显示页面,我只是无法注入所需的 JS。
我在转换中所做的一切都非常简单,除了分配 userContentController 外,几乎不需要更改或不需要更改 - 所以也许这就是问题所在?这个例子在 iOS 中工作得很好,他的原始样本作为原型。 https://github.com/rckim77/WKWebViewDemoApp/blob/master/WKWebViewDemoApp/ViewController.swift
我猜这里一定有一些非常简单的东西。任何帮助将不胜感激!
解决方案
以下是我在 Mac 上设置 WebView 的方法 试试这样
import Cocoa
import WebKit
class ViewController: NSViewController {
@IBOutlet weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let javascript = """
function printStatement() {
try {
window.webkit.messageHandlers
.callbackHandler.postMessage({'payload': 'Hello World!'})
} catch(err) {
console.log('The native context does yet exist')
}
}
"""
let script = WKUserScript(
source: javascript,
injectionTime: WKUserScriptInjectionTime.atDocumentEnd,
forMainFrameOnly: true
)
webView.configuration.userContentController.add(
name: "callbackHandler"
)
webView.configuration.userContentController
.addUserScript(script)
webView.navigationDelegate = self
let html = """
<div onClick='javascript:printStatement()'>Print Statement</div>
"""
webView.loadHTMLString(html, nil)
}
}
extension ViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if(message.name == "callbackHandler") {
guard let body = message.body as? [String: Any] else {
print("could not convert message body to dictionary: \(message.body)")
return
}
guard let payload = body["payload"] as? String else {
print("Could not locate payload param in callback request")
return
}
print(payload)
}
}
}
希望这能回答你的问题,如果不让我知道,我会努力解决的!
推荐阅读
- php - 如何在 PHP 中设置标题位置?
- sql - 跨多个列查找唯一数据的随机样本 - SQL Server
- javascript - CSS 类顺序对性能有影响吗?
- javascript - Javascript 函数 Object.keys 无法正常工作
- python - Pygame:图像没有出现在移动的背景上
- java - JPA 查询格式日期
- reactjs - 是否可以将 React 应用程序配置为在 Kubernetes 中使用容器的环境变量?
- delphi - Delphi 导出 HKEY_CURRENT_USER 密钥不起作用 - 空结果文件
- typescript - Typescript 基于接口从另一个对象创建一个对象
- python - 使用 BS4 的网页抓取问题 - 需要历史天气信息 - 文本静音