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?
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
, andenabled
.Starting in 10.11:
tag
,state
, andindentationLevel
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.