如何检查"复制的文本来自哪个应用程序"?

时间:2018-03-21 05:40:19

标签: swift cocoa nsapplication nspasteboard

最近,我正在开发基于Pasteboard的应用程序。我想知道复制的文本不会存储在选定的正在运行的应用程序的粘贴板中。有人有想法吗?

2 个答案:

答案 0 :(得分:1)

虽然你的问题有点不清楚,但我的理解是你想知道哪个应用程序只是在粘贴板上添加了一些东西(当然你也想要粘贴板的内容)。

虽然没有API,但还有一种方法。这是一种黑客攻击,但这就是Apple在他们的例子中如何做到这一点,所以我猜它没问题。

主要思想是定时轮询粘贴板,并同时观察.NSWorkspaceDidActivateApplication:这样我们就可以知道当粘贴板中出现新内容时哪个应用程序处于活动状态。

以下是执行此操作的类的示例:

class PasteboardWatcher {

    private let pasteboard = NSPasteboard.general()

    // Keep track of the changes in the pasteboard.
    private var changeCount: Int

    // Used to regularly poll the pasteboard for changes.
    private var timer: Timer?

    private var frontmostApp: (name: String, bundle: String)?

    init() {
        // On launch, we mirror the pasteboard context.
        self.changeCount = pasteboard.changeCount

        // Registers if any application becomes active (or comes frontmost) and calls a method if it's the case.
        NSWorkspace.shared().notificationCenter.addObserver(self, selector: #selector(activeApp(sender:)), name: .NSWorkspaceDidActivateApplication, object: nil)

        if let types = pasteboard.types {
            print("Available pasteboards: \(types)")
        }
    }

    // Start polling for changes in pasteboard.
    func startPolling() {
        self.timer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(checkForChangesInPasteboard), userInfo: nil, repeats: true)
    }

    // Called by NSWorkspace when any application becomes active or comes frontmost.
    @objc private func activeApp(sender: NSNotification) {
        if let info = sender.userInfo,
            let content = info[NSWorkspaceApplicationKey] as? NSRunningApplication,
            let name = content.localizedName,
            let bundle = content.bundleIdentifier
        {
            frontmostApp = (name: name, bundle: bundle)
        }
    }

    @objc private func checkForChangesInPasteboard() {
        if pasteboard.changeCount != changeCount {
            changeCount = pasteboard.changeCount
            if let copied = pasteboard.string(forType: NSStringPboardType),
                let app = frontmostApp
            {
                print("Copied string is: '\(copied)' from \(app.name) (\(app.bundle))")
            }
        }
    }

}

使用它就像这样:

let watcher = PasteboardWatcher()
watcher.startPolling()

它会在控制台中打印复制的字符串,还会显示应用程序的名称和包。

答案 1 :(得分:0)

没有API可以检索负责将数据放在粘贴板上的应用程序。

如果你想知道它是你自己的应用程序那么你必须自己处理它,否则你运气不好。