Finder Sync Extension: selectedItemURLs is null when used outside of the NSMenu

Hi there,

The Setup/My Goal

I have a very standard Finder Sync Extension, which extends the context menu of the finder. I also have a main application which uses the KeyboardShortcuts Package (Keyboard Shortcuts - Github) to record and save a user defined shortcut. This shortcut should execute the menu item of the Finder Sync Extension (therefore getting the selected files and processing them in some way) when used.

Currently I am using inter-process communication to send an event to the extension when the shortcut is executed by the user. You can find the Swift Class responsible for the communication between Finder Sync Extension and the Main App as an Attachment here:

(although the communication works and this is more an issue of the finder sync extension behaviour than one of inter-process communication).

When the Finder Sync Extension receives the event, it executes the same function which is called when the user clicks the menu item like so (this event is registered in the initialisation function of the Finder Sync Extension):

   processCommunicator = ProcessCommunicatorReceiver(appGroupIdentifier: "group.some.bundle.id.port")
   processCommunicator?.on(id: 1, event: { _ in
   	self.executeSomeAction(nil)
    	return nil
   })

The same action is called when the user clicks the menu item:

 override func menu(for menuKind: FIMenuKind) -> NSMenu {
        let menu = NSMenu()

        if menuKind == FIMenuKind.contextualMenuForItems || menuKind == FIMenuKind.toolbarItemMenu {

            menu.addItem(withTitle: text, action: #selector(executeSomeAction), keyEquivalent: "T")
        }
        return menu
    }

The function executeSomeAction would look something like this

 @IBAction func transfer(_ sender: AnyObject?) {
        guard let target = finderSyncController.selectedItemURLs() else {
            NSLog("Failed to obtain targeted URLs: %@")

            return
   }
	 // Process the selected items (target)

The Problem

When the function executeSomeAction is called from the process-communicator-event (sent by the main app), the selectedItemURLs is nil and therefore the function returns without doing anything. If the function executeSomeAction is called by the menu item click event, the selectedItemURLs is an array of paths as expected.

Is there some restriction which prevents access to the user selected, when it’s not strictly clicked by the user or am I missing something here?

Other possible Solutions to my Issue

This whole inter-process communication is only needed because I need the shortcut event to be sent to the extension. I have noticed that in the initialisier of the menu item there is a keyEquivalent (-> shortcut)

menu.addItem(withTitle: text, action: #selector(executeSomeAction),  /* HERE -->*/ keyEquivalent: "T")

This shortcut seems to be ignored by the system, as it neither appears next to the menu item, nor is functional. I am assuming that this is intended but if there is any way to make this work with the inbuilt system shortcut, instead of the communication-hack I am using currently, I would prefer to use this solution.

Summary

As said before, the selectedItemURLs is only defined if it is called from the menu item event, which eliminates the ability to do some custom processing with the selected files (in my case called by an event sent by another process)

Replies

Is there some restriction which prevents access to the user selected, when it’s not strictly clicked by the user or am I missing something here?

There are restrictions.

From the documentation:

This method returns valid values only from the Finder Sync extension’s menuForMenuKind: method or from one of the menu actions created in this method. If the selected items are outside the extension’s managed directories (for example, when the user clicks on the toolbar button), this method returns nil.

https://developer.apple.com/documentation/findersync/fifindersynccontroller/1501575-selecteditemurls?language=objc