You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在SafariExtensionHandler中设置NSTextField值导致扩展崩溃

问题:Safari扩展点击按钮后崩溃,无法更新NSTextField内容

在SafariExtensionHandler.swift中尝试设置文本时,菜单栏的Safari扩展直接崩溃。目标网页能输出日志“Loaded”和“Send to script”,但之后扩展就崩溃了。预期是点击按钮后,NSTextField显示文本:“Javascript: Send to script”。

SafariExtensionViewController.swift

import SafariServices

class SafariExtensionViewController: SFSafariExtensionViewController {
    
    static let shared: SafariExtensionViewController = {
        let shared = SafariExtensionViewController()
        shared.preferredContentSize = NSSize(width:320, height:240)
        return shared
    }()
    
    @IBOutlet weak var textBox: NSTextField!
    
    @IBAction func buttonClicked(_ sender: Any) {
        sendMessage(messageStr: "Send to script")
    }
    
    func setStringValue(strVal: String){
        textBox.stringValue = strVal
    }
    
    func sendMessage(messageStr: String) {
        getActivePage {
            $0?.dispatchMessageToScript(withName: messageStr)
        }
    }
    
    func getActivePage(completionHandler: @escaping (SFSafariPage?) -> Void) {
        SFSafariApplication.getActiveWindow {$0?.getActiveTab {$0?.getActivePage(completionHandler: completionHandler)}}
    }
}

SafariExtensionHandler.swift

import SafariServices
import os.log

class SafariExtensionHandler: SFSafariExtensionHandler {

    override func beginRequest(with context: NSExtensionContext) {
        let request = context.inputItems.first as? NSExtensionItem

        let profile: UUID?
        if #available(iOS 17.0, macOS 14.0, *) {
            profile = request?.userInfo?[SFExtensionProfileKey] as? UUID
        } else {
            profile = request?.userInfo?["profile"] as? UUID
        }

        os_log(.default, "The extension received a request for profile: %@", profile?.uuidString ?? "none")
    }

    override func messageReceived(withName messageName: String, from page: SFSafariPage, userInfo: [String : Any]?) {
        page.getPropertiesWithCompletionHandler { properties in
            os_log(.default, "The extension received a message (%@) from a script injected into (%@) with userInfo (%@)", messageName, String(describing: properties?.url), userInfo ?? [:])
        }
        SafariExtensionViewController().setStringValue(strVal: messageName)
    }

    override func toolbarItemClicked(in window: SFSafariWindow) {
        os_log(.default, "The extension's toolbar item was clicked")
    }

    override func validateToolbarItem(in window: SFSafariWindow, validationHandler: @escaping ((Bool, String) -> Void)) {
        validationHandler(true, "")
    }

    override func popoverViewController() -> SFSafariExtensionViewController {
        return SafariExtensionViewController.shared
    }

}

script.js

document.addEventListener("DOMContentLoaded", function(event) {
    console.log("Loaded");
});

safari.self.addEventListener("message", handleMessage);

function handleMessage(event) {
    safari.extension.dispatchMessage("Javascript: " + event.name);
    console.log(event.name);
}

已尝试的解决方法:

  • 使用NSTextFieldCell来引用NSTextField
  • 在Handler.swift中直接引用NSTextField实例
  • 先将响应消息存入变量,再设置NSTextField的值

内容的提问来源于stack exchange,提问作者SmokinPatty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 12:00:26