Question Details

No question body available.

Tags

swift cocoa appkit nsmenu continuity

Answers (1)

February 8, 2026 Score: 0 Rep: 364 Quality: Low Completeness: 80%

NSMenuToolbarItem menus don't participate in the responder chain the same way main menus and contextual menus do; Continuity Camera relies entirely on responder-chain discovery at menu-validation time.

In your code, you're attaching the menu directly to the toolbar item which prevents AppKit from walking the responder chain which causes continuity camera to not be discovered.

Basically Continuity Camera menu items are not static menu items, they are injected during menu validation and they're also based on the current first responder; they can be discovered through responder methods as well.

Apple treats toolbar menus more like popover menus than "command menus": they don't automatically validate against the first responder, they also don't walk the responder chain. In essence, they don't trigger Continuity Camera discovery, even though the same NSMenu works in the main menu and as a contextual menu, it will never expand continuity camera actions when attached directly to an NSMenuToolbarItem.

The only way reliable workaround would be to not attach the menu directly to NSMenuToolbarItem and instead use a plain NSToolbarItem; on click you could then present a menu relative to the active NSTextView.

You could do something like this:

// Adjust as needed for your own use-case
func toolbar(
     toolbar: NSToolbar,
    itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
    let item = NSToolbarItem(itemIdentifier: itemIdentifier)
    item.label = "Import"
    item.target = self
    item.action = #selector(showImportMenu(:))
    return item
}

@objc private func showImportMenu( sender: Any?) { guard let window = NSApp.keyWindow, let textView = window.firstResponder as? NSTextView else { return }

// this is assuming storyboardMenu is the same menu // containing “Import from Device” placeholder item. let menu = storyboardMenu

/* Here, you can present the menu relative to the textView so the responder chain is used; i'm positioning the menu in the coordinate space of textView. AppKit treats it as originating from that view just like a contextual menu.

The exact coordinates are not super critical for Continuinty Camera; the important part is in the in: textView parameter */ let point = NSPoint(x: 0, y: textView.bounds.maxY) menu.popUp( positioning: nil, at: point, in: textView ) }

You could just as well do:

let point = textView.convert(NSPoint.zero, to: nil)or anchor it near the insertion point if you want a tighter UX.

Update 2/8/26

enter image description here

let itemIdentifier = NSToolbarItem.Identifier("com.continuitycamera.import")

private let storyboardMenu: NSMenu = { let menu = NSMenu() let item = NSMenuItem( title: "Import", action: nil, keyEquivalent: "" ) item.identifier = NSUserInterfaceItemIdentifier("NSMenuItemImportFromDevice") menu.addItem(item) return menu }()

func toolbarDefaultItemIdentifiers(
toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { [itemIdentifier] }

func toolbarAllowedItemIdentifiers( toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { [itemIdentifier] }

func toolbar(
toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? { let item = NSToolbarItem(itemIdentifier: itemIdentifier) item.label = "Import" item.target = self item.action = #selector(showImportMenu(:))

if let image = NSImage(systemSymbolName: "camera.badge.ellipsis", accessibilityDescription: "Import from Device") { image.isTemplate = true item.image = image } return item }

@objc private func showImportMenu(
sender: Any?) { guard let window = NSApp.keyWindow, let textView = window.firstResponder as? NSTextView else { return } let menu = storyboardMenu let point = NSPoint(x: 0, y: textView.bounds.maxY) menu.popUp( positioning: nil, at: point, in: textView ) }