Swift macOS:如何粘贴到另一个应用程序中

Neo*_*ant 5 macos cocoa operating-system swift

我正在使用swift为Mac OS 10.10+编写一个辅助应用程序.我需要能够将通用NSPasteboard中的内容粘贴到之前处于活动状态的应用程序中.

只是为了说清楚:我需要粘贴到另一个应用程序中.

它应该像这样工作:

  1. 用户正在使用一些随机应用程序

  2. 因为用户因残疾而无法按下cmd + v,所以他们会做出一个手势来激活我的应用程序(此部分已完成并且超出了此问题的范围)

  3. 我的应用程序变为活动状态,现在我需要在用户预先使用的应用程序中模拟粘贴操作.这是我不知道怎么做的.

  4. 最后,以前活跃的应用程序需要再次激活.

请记住,该应用程序将提交给AppStore.

小智 8

我发现这些命令可以使用 Foundation 模拟剪切/复制/粘贴:

func pastematchstyle () {

    let event1 = CGEvent(keyboardEventSource: nil, virtualKey: 0x09, keyDown: true); // opt-shft-cmd-v down
    event1?.flags = [CGEventFlags.maskCommand, CGEventFlags.maskShift, CGEventFlags.maskAlternate]
    event1?.post(tap: CGEventTapLocation.cghidEventTap);

    let event2 = CGEvent(keyboardEventSource: nil, virtualKey: 0x09, keyDown: false); // opt-shf-cmd-v up
 //   event2?.flags = [CGEventFlags.maskCommand, CGEventFlags.maskShift, CGEventFlags.maskAlternate]
    event2?.post(tap: CGEventTapLocation.cghidEventTap);

}

func paste () {

    let event1 = CGEvent(keyboardEventSource: nil, virtualKey: 0x09, keyDown: true); // cmd-v down
    event1?.flags = CGEventFlags.maskCommand;
    event1?.post(tap: CGEventTapLocation.cghidEventTap);

    let event2 = CGEvent(keyboardEventSource: nil, virtualKey: 0x09, keyDown: false) // cmd-v up
//    event2?.flags = CGEventFlags.maskCommand
    event2?.post(tap: CGEventTapLocation.cghidEventTap)


}


func pasteresults () {

    let event1 = CGEvent(keyboardEventSource: nil, virtualKey: 0x09, keyDown: true); // shft-cmd-v down
    event1?.flags = [CGEventFlags.maskCommand, CGEventFlags.maskShift]
    event1?.post(tap: CGEventTapLocation.cghidEventTap);

    let event2 = CGEvent(keyboardEventSource: nil, virtualKey: 0x09, keyDown: false); // shf-cmd-v up
//    event2?.flags = [CGEventFlags.maskCommand, CGEventFlags.maskShift];
    event2?.post(tap: CGEventTapLocation.cghidEventTap);



}


func cut() {


    let event1 = CGEvent(keyboardEventSource: nil, virtualKey: 0x07, keyDown: true); // cmd-x down
    event1?.flags = CGEventFlags.maskCommand;
    event1?.post(tap: CGEventTapLocation.cghidEventTap);

    let event2 = CGEvent(keyboardEventSource: nil, virtualKey: 0x07, keyDown: false); // cmd-x up
//    event2?.flags = CGEventFlags.maskCommand;
    event2?.post(tap: CGEventTapLocation.cghidEventTap);

}





func copy() {


    let event1 = CGEvent(keyboardEventSource: nil, virtualKey: 0x08, keyDown: true); // cmd-c down
    event1?.flags = CGEventFlags.maskCommand;
    event1?.post(tap: CGEventTapLocation.cghidEventTap);

    let event2 = CGEvent(keyboardEventSource: nil, virtualKey: 0x08, keyDown: false); // cmd-c up
//    event2?.flags = CGEventFlags.maskCommand;
    event2?.post(tap: CGEventTapLocation.cghidEventTap);

}


func copystyle() {

    let event1 = CGEvent(keyboardEventSource: nil, virtualKey: 0x08, keyDown: true); // opt-cmd-c down
    event1?.flags = [CGEventFlags.maskCommand, CGEventFlags.maskAlternate];
    event1?.post(tap: CGEventTapLocation.cghidEventTap);

    let event2 = CGEvent(keyboardEventSource: nil, virtualKey: 0x08, keyDown: false); // opt-cmd-c up
    //    event2?.flags = CGEventFlags.maskCommand;
    event2?.post(tap: CGEventTapLocation.cghidEventTap);


}

func pastestyle() {

    let event1 = CGEvent(keyboardEventSource: nil, virtualKey: 0x07, keyDown: true); // opt-cmd-v down
    event1?.flags = [CGEventFlags.maskCommand, CGEventFlags.maskAlternate];
    event1?.post(tap: CGEventTapLocation.cghidEventTap);

    let event2 = CGEvent(keyboardEventSource: nil, virtualKey: 0x07, keyDown: false); // opt-cmd-v up
    //    event2?.flags = CGEventFlags.maskCommand;
    event2?.post(tap: CGEventTapLocation.cghidEventTap);

}
Run Code Online (Sandbox Code Playgroud)


mz2*_*mz2 5

最简单的是你需要做两件事:

  1. 订阅当前应用程序更改的通知,以便您知道应将事件发送到哪个应用程序.

  2. 使用系统事件模拟Cmd + V按键.

但是,坏消息是,正如您所说,您需要在App Store提交的应用程序中执行此操作,您的应用程序需要位于沙箱内,并且需要临时授权com.apple.security.temporary-exception.apple-events才能直接向System Events发送事件并引用Apple文档:

在应用程序审核过程中,为Finder和系统事件请求必要的Apple事件临时例外权利可能会导致拒绝,因为授予对这些进程的访问权限可以让您的应用程序免费控制大部分操作系统.对于系统级任务,请使用其他方法,如上所述.

还有一种方法可以使用辅助技术执行第2步,但这也不适用于沙箱.从根本上说,你要做的事情(激活一个外部的任意应用程序,并控制它)几乎就是沙盒的设计目的是阻止你做什么.

幸运的是,由于macOS 10.8现在有NSUserAppleScriptTask,它在沙箱之外执行.

有一个转折NSUserAppleScriptTask:执行的脚本NSUserAppleScriptTask需要放在应用程序的脚本目录中,并且您的应用程序无法写入,只能从中读取.

这篇objc.io文章展示了一个示例,说明如何请求对脚本目录进行安全范围写入访问,以便能够将脚本编写到脚本目录中; 对于你自己和你的用户来说,你需要第一次打开一个打开的对话框,因此,你需要存储安全范围的书签,这样你就不需要重复练习,但这是你能做到的最好的在沙箱内做.

除了NSUserAppleScriptTask我的知识之外,你唯一的另一条路线就是说服Apple,这是一个非常好的主意,接受你的应用程序的临时权利,允许它编写系统事件脚本(我不会屏住呼吸).