4

I would like to handle open events when a user double-clicks on a file that was created by my application, or drags such a file onto the dock icon.

I've therefore implemented NSApplicationDelegate's application:openFile: and application:openFiles: methods, which work as expected when the application is not running.

However, if the application is already running when the open event occurs, the application becomes focused, but the above methods are never called (breakpoints inside them are not hit) and the files do not open.

I also tried implementing application:openURLs:. This method has the same behaviour: it is not called if the application is already running when the event occurs.

Do I need to implement different functions to handle opening files when the application is already running, or is there something else I need to do/set in order for the existing functions to be called in those circumstances?

Rich
  • 7,348
  • 4
  • 34
  • 54
  • Is the app document-based? – Willeke Jun 23 '18 at 11:36
  • @Willeke It is not. – Rich Jun 23 '18 at 21:40
  • How can I reproduce the issue in a new project? – Willeke Jun 24 '18 at 12:59
  • @Willeke Implement [`application:openFile:`](https://developer.apple.com/documentation/appkit/nsapplicationdelegate/1428612-application?language=objc) on your app delegate, set a file to open in your app in Finder's `Get Info -> Open with:` section, and then double click on that file in the Finder. I haven't actually tried reproducing the issue in a new project: I was hoping there was a simple answer. It's starting to look like it's not just a straightforward misreading of the docs, though, so I guess that's the next step. – Rich Jun 25 '18 at 08:59
  • 1
    I tried this and it works. – Willeke Jun 25 '18 at 11:39
  • 1
    @Willeke So I'm using the correct API, but there's some other setting/code in my project that is preventing it from working when the app is already running. Thanks for the info. – Rich Jun 25 '18 at 11:43
  • @Willeke Many thanks for helping to diagnose the issue. See my answer below for the cause. – Rich Jun 25 '18 at 13:30

2 Answers2

4

This is not mentioned in the documentation, but according to this answer the way that application:openFile: works is that it NSApplication forwards odoc Apple Events to its delegate.

Armed with this knowledge, I was able to find the following old Carbon call in the app:

osError = AEInstallEventHandler(kCoreEventClass,
                                kAEOpenDocuments,
                                g_OpenDocumentsUPP,
                                0L,
                                false);

I'm presuming this existing event handler consumed the Apple Event before NSApplication had a chance to deal with it. However, when the app is not already running, NSApplication handles the event before the line above setting up the event handler is called, hence the different behaviour.

Removing this old code from the build caused the NSApplicationDelegate methods to be called, thus fixing the issue.

Rich
  • 7,348
  • 4
  • 34
  • 54
1

Does the following method work?

- (void)application:(NSApplication *)application 
       openURLs:(NSArray<NSURL *> *)urls;

If your delegate implements this method, AppKit does not call the
application:openFile: or application:openFiles: methods.
MyCometG3
  • 167
  • 1
  • 10
  • `application:openURLs:` has the same behaviour: it works correctly when the application is *not* running, but it is not called when the application *is* already running. – Rich Jun 25 '18 at 08:53