Macos 当使用NSWorkspace在应用程序之间打开URL时,如何发送和接收NSAppleEventDescriptor?

Macos 当使用NSWorkspace在应用程序之间打开URL时,如何发送和接收NSAppleEventDescriptor?,macos,appkit,nsworkspace,appleevents,nsapplication-delegate,Macos,Appkit,Nsworkspace,Appleevents,Nsapplication Delegate,NSWorkspace打开了方法(\u1:withAppBundleIdentifier:[…]): 从URL数组中打开一个或多个文件 要打开的应用程序的NSApplicationLegate具有相应的方法,这些方法将被调用以打开您提供的URL: func application(_ sender: NSApplication, openFile filename: String) -> Bool func application(_ sender: NSApplication, ope

NSWorkspace打开了方法
(\u1:withAppBundleIdentifier:[…])

从URL数组中打开一个或多个文件


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

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

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

附加事件参数描述符:NSAppleEventDescriptor?

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


我想向将打开文件的应用程序发送其他信息。 这将类似于通知中的
userInfo
字典

我构造了一个
NSAppleEventDescriptor
对象来表示此信息。我可以在NSWorkspace
open(…)
函数中设置此事件描述符

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

应用程序(uquo;openFile:)
函数没有用于事件描述符或任何其他“
userInfo
”类型附加信息的参数


代码 根据答案和其他问题,我确定了以下解决方案。我现在得到一个苹果事件的触发处理程序。但是我在NSWorkspace函数上设置的Apple事件不是处理程序中接收到的事件!如何取而代之的是我的苹果活动


发送 已发送Apple事件:


接收 收到苹果事件:

Kaeopendoments事件方法
-[NSWorkspace openURLs:…]
生成一个
kAEOpenDocuments
事件,其中包含URL作为沙盒保存书签数据。(请参见
+[NSURL URLByResolvingBookmarkData:options:relativeToURL:bookmarkDataIsStale:error:

additionalEventParamDescriptor:

使用自定义参数创建带有
kAEOpenDocuments
的additionalEventParamDescriptor时,此事件似乎与来自
-[NSWorkspace OpenURL:…]的底层kAEOpenDocuments事件合并

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…)

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

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

>>>执行此操作时,服务器会向
odoc
事件添加一个附加参数。“您的应用程序将只接收以其为目标的Apple事件,即在其目标地址描述符中指定您的应用程序的事件。”查看控制台日志
AppleEvents未能对/Users/user/Desktop的扩展名进行编码,err=Operation not allowed/1
-这是我在Apple脚本中发送的目标之一…不要费心传递额外的EventParamDescriptor。很难正确,而且我已经看到证据表明它甚至没有正确传递。(我已经直接使用Launch Services,它确实正确地传递了参数。)我使用的是
eventClass:AEEventClass(kCoreEventClass),eventID:AEEventID(Kaeopendictions)
。我得到了回调,但奇怪的是,它在处理程序中似乎是一个完全不同的事件。我应该使用什么类/ID?或者事件在传输过程中发生更改还有其他原因吗?从我看到的情况来看,您得到的是Kaeopendiuments事件,而不是其他事件。这是有意义的。但我也无法获得自定义事件处理程序我更新了我的答案,从来没有做过你想做的事情。只记得前一段时间玩过一些相关的东西,以为我会尝试一下。问题是,即使我没有在NSWorkspace函数调用中包含
additionalEventParamDescriptor:
,我的处理程序也会被触发。在这两种情况下,在在e handler中,事件显示为带有直接对象的“bookmark”事件:
希望更新后的答案能够澄清问题……仍然需要解析Kaeopendoments事件。
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)
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)
    }
    
}
- (void)applicationWillFinishLaunching:(NSNotification *)notification {
    [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleAppleEvent:withReplyEvent:) forEventClass:kCoreEventClass andEventID:kAEOpenDocuments];
}

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

}
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];