Łukasz
Łukasz

Reputation: 805

How to make ContextMenu in NewView:NSViewRepresentable?

I have an old OldNSView : NSView, which is embedded in SwiftUI NewView<S:SomeProtocol> : NSViewRepresentable struct. And I need to add a context menu. But when I try to create NSMenuItems for oldNsView.menu, they asks for #Selector, which needs @objc func ... to work. Because it's inside SwiftUI View compiler doesn't allow to do it. (With no #selectors defined I can see menu items labels (of course they are greyed-out and they do nothing).

On the second hand, If I try to add .contextMenu to SwiftUI newView nothing happens. No menu at all. It works with Text(...) or another generic views but not with custom NSViewRepresentable struct.

All mouseUp(with event..), mouseDown(), and mouseDragged() call super.mouse..(with event)

if I use Coordinator

public class Coordinator: NSObject {
    ...
    //Compiler does't like if (_ sender: OldView).
    //It likes (_ sender: NSView), but in this case context menu is grayed-out
    @objc func changeXAxis(_ sender: NSView) {
        if let view = sender as? OldView {
            print ("changeXAxis") 
        }
    }
}

Is there a way to do it?

Upvotes: 0

Views: 508

Answers (1)

Asperi
Asperi

Reputation: 258247

You have coordinator concept in representable to handle interaction with NSView.

Here is simple demo. Tested with Xcode 11.4 / macOS 10.15.5

demo

struct DemoViewWithMenu: NSViewRepresentable {
    func makeNSView(context: Context) -> NSView {
        let view = NSView()

        let menu = NSMenu()
        let item = menu.addItem(withTitle: "Do Action", action: #selector(Coordinator.action(_:)), keyEquivalent: "")
        item.target = context.coordinator
        
        view.menu = menu
        return view
    }

    func updateNSView(_ nsView: NSView, context: Context) {
    }

    func makeCoordinator() -> Coordinator {
        Coordinator()
    }

    class Coordinator: NSObject {
        @objc func action(_ sender: Any) {
            print(">> do action here")
        }
    }
}

Upvotes: 1

Related Questions