I thought I was so slick in rewriting my handler for the "Open" menu command in the application delegate:
- (IBAction)openDocument:(id)sender {
NSOpenPanel * const panel = [NSOpenPanel openPanel];
panel.allowsMultipleSelection = YES;
panel.delegate = self;
[panel beginWithCompletionHandler:^(NSInteger result) {
if (result == NSFileHandlingPanelOKButton) {
NSMutableArray * const paths = [NSMutableArray arrayWithCapacity:panel.URLs.count];
for (NSURL *file in panel.URLs) {
[paths addObject:file.path];
}
[self application:NSApp openFiles:paths];
}
}];
}
In the old code, looping through each file URL, I used to call my window creation code directly. Then I swapped out implementing the single-file -application:openFile:
for its multi-file variant, and decided to reuse that code within -openDocument:
.
I thought it was fine.
The single-file version return a BOOL indicating its success. For the multi-file version, you're supposed to call a special function of the application object.
I guess when you start up your app with some files, Cocoa's handler looks at them with the open-file AppleEvent, calls -application:openFiles:
, waits for the response global to be set, then sends back and AppleEvent reply. When I reuse -application:openFiles:
in -openDocument
, I post to that global when the application object isn't expecting it.... Oh, crap.
Oh, I could submit the files for processing by putting them in an open-file AppleEvent and sending to self. I look around the docs, and I see everything except what I need: how to send an AppleEvent and the list of possible AppleEvents and their parameters.
Could someone here demostrate how to create and send an open-file AppleEvent? Or at least tell us where the table of event IDs and parameters are? (The various Cocoa guides on scripting refer to the event ID reference, but it's a dead link, leading to Apple's developer portal general/search page.)
I just guessed:
- (IBAction)openDocument:(id)sender {
NSOpenPanel * const panel = [NSOpenPanel openPanel];
panel.allowsMultipleSelection = YES;
panel.delegate = self.openPanelDelegate;
[panel beginWithCompletionHandler:^(NSInteger result) {
if (result == NSFileHandlingPanelOKButton) {
NSAppleEventDescriptor * const fileList = [NSAppleEventDescriptor listDescriptor];
NSAppleEventDescriptor * const openEvent = [NSAppleEventDescriptor appleEventWithEventClass:kCoreEventClass eventID:kAEOpenDocuments targetDescriptor:nil returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID];
for (NSURL *file in panel.URLs) {
[fileList insertDescriptor:[NSAppleEventDescriptor descriptorWithDescriptorType:typeFileURL data:[[file absoluteString] dataUsingEncoding:NSUTF8StringEncoding]] atIndex:0];
}
[openEvent setParamDescriptor:fileList forKeyword:keyDirectObject];
[[NSAppleEventManager sharedAppleEventManager] dispatchRawAppleEvent:[openEvent aeDesc] withRawReply:(AppleEvent *)[[NSAppleEventDescriptor nullDescriptor] aeDesc] handlerRefCon:(SRefCon)0];
}
}];
}
looking at the docs for "NSAppleEventManager.h" and "NSAppleEventDescriptor.h" and half-remembering Mac programming materials I read in the 1990s.
I also poked around the Legacy/Retired Documents section of Apple's Developer Portal / Xcode.