如何使用 Swift 将鼠标悬停在 URL 上进入 WkWebView

how to get mouse over URLs into WkWebView with Swift

作为 的后续行动,我有一个相关问题,但使用 Swift。

我需要在鼠标悬停时获取 URL,作为上下文菜单出现的前奏,因此我可以将其注入菜单项的 respresentedObject - 或者以其他方式保存。某些项目的内置操作未得到正确处理。

我发现 'Open Link' 的菜单项操作正常,但 'Open Link in New Window' 不行;这些都不是通过内置的上下文菜单项操作来工作的。我想支持一个中间按钮点击成为后面的菜单项。

所以,使用原始 post 作为基础我有这个 - 我还子 class WkWebView,添加

class MyWebView : WKWebView {
    var selectedText : String?
    var selectedURL : URL?
}

然后在视图控制器中

func viewDidLoad() {
    //  Watch javascript selection messages
    let controller = webView.configuration.userContentController
    controller.add(self, name: "newSelectionDetected")
    let js = """
function getSelectionAndSendMessage()
{
    var txt = document.getSelection().toString() ;
    window.webkit.messageHandlers.newSelectionDetected.postMessage(txt) ;
}
document.onmouseup   = getSelectionAndSendMessage ;
document.onkeyup     = getSelectionAndSendMessage ;
"""

    let script = WKUserScript.init(source: js, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
    controller.addUserScript(script)
}

// MARK: Javascript

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    Swift.print("userContentController")

    // A new selected text has been received
    if let urlString : String = message.body as? String
    {
        webView.selectedText = urlString
        Swift.print("ucc: str -> \(urlString)")
    }
    if let url = message.frameInfo.request.url {
        webView.selectedURL = url
        Swift.print("ucc: url -> \(url.absoluteString)")
    }
}

// MARK: callbacks
override func willOpenMenu(_ menu: NSMenu, with event: NSEvent) {

    //  Pick off javascript items we want to ignore or handle
    for title in ["Open Link", "Open Link in New Window", "Download Linked File"] {
        if let item = menu.item(withTitle: title) {
            if title == "Download Linked File" {
                menu.removeItem(item)
            }
            else
            if title == "Open Link"
            {
                item.representedObject = self.window
                item.action = #selector(MyWebView.openLinkInWindow(_:))
                item.target = self
            }
            else
            {
                item.action = #selector(MyWebView.openLinkNewWindow(_:))
                item.target = self
            }
        }
    }
}

在我的动作处理程序中,我只得到框架的 URL,而不是鼠标悬停时突出显示的内容。

我需要的是获取 URL 等,如鼠标悬停在 Web 浏览器的状态栏中所示,以便缓存上下文菜单项的操作。

好吧,我想,在您的 javascript 中,您需要向所有 link 添加一个 onmouseover 事件处理程序,并且此事件处理程序应该将 link 发回到 swift 世界。

根据您的代码,我会在 Javascript 中添加类似以下内容:

function sendLink()
{
    window.webkit.messageHandlers.newUrlDetected.postMessage(this.href) ;
}

var allLinks = document.links;
for(var i=0; i< allLinks.length; i++)
{
    allLinks[i].onmouseover = sendLink ;
}

当然,在 Swift 世界中,您需要赶上 "newUrlDetected"

controller.add(self, name: "newUrlDetected")

并且在 Swift 消息处理程序中,您需要切换 WKScriptMessage 名称 属性。

  • 如果是"newSelectionDetected",则在邮件正文中设置webView.selectedText
  • 如果是"newUrlDetected",则设置webView.selectedURL与消息正文