2

NSWorkspace 有方法open(_:withAppBundleIdentifier: [...] )

从一组 URL 打开一个或多个文件。

func open(_ urls: [URL], 
     withAppBundleIdentifier bundleIdentifier: String?, 
     options: NSWorkspace.LaunchOptions = [], 
     additionalEventParamDescriptor descriptor: NSAppleEventDescriptor?, 
     launchIdentifiers identifiers:) -> Bool

您要打开的应用程序的 NSApplicationDelegate具有相应的方法,这些方法会被调用以打开您提供的 URL:

func application(_ sender: NSApplication, openFile filename: String) -> Bool
func application(_ sender: NSApplication, openFiles filenames: [String])

回到open(_:withAppBundleIdentifier: [...]),该方法有一个 NSAppleEventDescriptor 参数:

additionalEventParamDescriptor descriptor: NSAppleEventDescriptor?
在 AppleEvent 样式描述符中指定的附加选项。例如,您可以使用此参数指定在启动应用程序时要打开的其他文档。


我想向将打开文件的应用程序发送其他信息。

这将与userInfo通知中的字典类似地使用。

我已经构建了一个NSAppleEventDescriptor对象来表示这些信息。open( ... )我可以在 NSWorkspace函数中设置这个事件描述符。

但是如何在目标应用程序的应用程序委托中接收此事件描述符?

这些application(_: openFile:)函数没有事件描述符的参数或任何其他“ userInfo”类型的附加信息。


代码

根据答案和其他问题,我确定了以下解决方案。我现在得到了 Apple 事件的触发处理程序。但是我在 NSWorkspace 函数上设置的 Apple 事件不是处理程序中收到的事件!我如何获得我的Apple Event?


发送

let appleEvent = NSAppleEventDescriptor(eventClass:       AEEventClass(kCoreEventClass),
                                        eventID:          AEEventID(kAEOpenDocuments),
                                        targetDescriptor: nil,
                                        returnID:         AEReturnID(kAutoGenerateReturnID),
                                        transactionID:    AETransactionID(kAnyTransactionID))
appleEvent.setDescriptor(NSAppleEventDescriptor(string: "THIS IS A TEST"), forKeyword: keyDirectObject)

let didOpen = AppKit.NSWorkspace.shared.open([URL(fileURLWithPath: "/path/image.png")],
                                             withAppBundleIdentifier: bundleID,
                                             options: [.withErrorPresentation],
                                             additionalEventParamDescriptor: appleEvent,
                                             launchIdentifiers: nil)

发送苹果事件:

<NSAppleEventDescriptor: 'aevt'\'odoc'{ '----':'utxt'("THIS IS A TEST") }>


收到

class AppDelegate: NSObject, NSApplicationDelegate {
    
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        NSAppleEventManager.shared().setEventHandler(self,
                                                     andSelector: #selector(handle(event:replyEvent:)),
                                                     forEventClass: AEEventClass(kCoreEventClass),
                                                     andEventID: AEEventID(kAEOpenDocuments))
    }
    
    @objc func handle(event: NSAppleEventDescriptor?, replyEvent: NSAppleEventDescriptor?) {
        guard let event = event,
            event.eventClass == AEEventClass(kCoreEventClass) && event.eventID == AEEventID(kAEOpenDocuments) else {
            return
        }

        guard let additionalEventParamDescriptor = event.paramDescriptor(forKeyword: keyAEPropData) else {
            return
        }

        
        guard let directObject = additionalEventParamDescriptor.paramDescriptor(forKeyword: keyDirectObject) else {
            return
        }
        
        print(directObject)
    }
    
}

收到苹果事件:

<NSAppleEventDescriptor: 'aevt'\'odoc'{ '----':[ 'bmrk'(888/$626F6F6B7803000000000 [....] 00000AC01000000000000...$) ] }>

4

1 回答 1

2

kAEOpenDocuments 事件方法

- (void)applicationWillFinishLaunching:(NSNotification *)notification {
    [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleAppleEvent:withReplyEvent:) forEventClass:kCoreEventClass andEventID:kAEOpenDocuments];
}

- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent {

}

-[NSWorkspace openURLs: ...]生成一个kAEOpenDocuments包含 URL 作为沙盒保存书签数据的事件。(见+[NSURL URLByResolvingBookmarkData: options: relativeToURL: bookmarkDataIsStale: error:])。

附加事件参数描述符:

当使用自定义参数创建additionalEventParamDescriptorkAEOpenDocuments,此事件似乎与来自-[NSWorkspace openURLs: ...].

NSAppleEventDescriptor *targetDescriptor = nil;
NSAppleEventDescriptor *appleEvent = nil;

targetDescriptor = [NSAppleEventDescriptor descriptorWithDescriptorType:typeApplicationBundleID
                                                                   data:targetBundleID];
appleEvent = [NSAppleEventDescriptor appleEventWithEventClass:kCoreEventClass
                                                      eventID:kAEOpenDocuments
                                             targetDescriptor:targetDescriptor
                                                     returnID:kAutoGenerateReturnID
                                                transactionID:kAnyTransactionID];
[appleEvent setParamDescriptor:[NSAppleEventDescriptor descriptorWithString:@"You're so good looking"]
                    forKeyword:'urln'];

[[NSWorkspace sharedWorkspace] openURLs:@[ [[NSBundle mainBundle] resourceURL] ]
                withAppBundleIdentifier:bundleIdentifier
                                options:NSWorkspaceLaunchNewInstance
         additionalEventParamDescriptor:appleEvent
                      launchIdentifiers:NULL];

示例 lldb 输出:

NSAppleEventDescriptor: 'aevt'\'odoc'{ ~'prdt':'aevt'\'odoc'{ 'urln':'utxt'("你真好看") }, '----':[ 'bmrk'(1432/$626F6F6B980 ...) }

注意:当为 kAEOpenDocuments设置NSAppleEventManager时,这会覆盖或方法的 AppKits 内置功能。自定义事件处理程序需要实现所有这些。application:openFile:application:openFiles:

自定义事件方法

根据我的发现,发送具有自定义事件 ID 的自定义事件类不会触发事件处理程序。¯_(ツ)_/¯

于 2019-08-12T09:39:09.393 回答