cocoansmenunsmenuitemappstore-sandboxfindersync

Weird behavior of Finder Sync Extension's tool bar item menu


I am building a macOS app with Finder Sync Extension, which adds a tool bar item to the Finder.

I created the tool bar item menu like this:

- (NSMenu *)menuForMenuKind:(FIMenuKind)whichMenu {
    NSMenu *menu = [NSMenu new];

    NSURL *URL = ...// Create a NSURL dynamically

    NSMenuItem *item = [NSMenuItem new];
    [item setTitle:@"foo"];
    [item setRepresentedObject:URL];
    [item setTarget: self];
    [item setAction:@selector(itemClicked:)];

    [menu addItem:item];

    return menu;
}

- (void)itemClicked:(NSMenuItem *)item {
    NSLog(@"%@", item.representedObject);
}

The item did show up with the title "foo", but when I click on it (null) was printed out.

I also tried creating a subclass of NSMenuItem with @property (NSURL*) URL, and set the URL property when I create the item, but after the click the URL property become nil again.

So what went wrong here?


Solution

  • The menu and menu items shown when you right click in Finder are copies of the menu items you provide in menu(for menu: FIMenuKind).

    Not all of your menu item's properties will survive the copy, leading to the nil value you're getting for representedObject. An NSMenuItem subclass will also definitely not be preserved.

    See the FinderSync header for more information from Apple:

    optional public func menu(for menu: FIMenuKind) -> NSMenu?

    Specific menu item properties are used: title, action, image, and enabled.

    Starting in 10.11: tag, state, and indentationLevel also work, and submenus are allowed.

    Using the menu item's title string or tag to determine the needed URL is probably the best available option.