Estou tentando escrever uma versão para macOS de https://stackoverflow.com/a/74935849/2178159 .
Pelo que entendi, eu deveria conseguir definir a menu
propriedade de um NSResponder
e ela será exibida automaticamente ao clicar com o botão direito.
Eu tentei algumas coisas:
A: definido menu
em um NSHostingController
's view
- quando eu faço isso e clico com o botão direito ou ctrl, nada acontece. B: definido menu
diretamente NSHostingController
- quando eu faço isso, ocorre um travamento Abstract method -[NSResponder setMenu:] called from class _TtGC7SwiftUI19NSHostingControllerGVS_21_ViewModifier_...__. Subclasses must override
C: chamada manual NSMenu.popup
em uma subclasse personalizada do método NSHostingController
ou NSView
's rightMouseDown
- nada acontece.
extension View {
func contextMenu(menu: NSMenu) -> some View {
modifier(ContextMenuViewModifier(menu: menu))
}
}
struct ContextMenuViewModifier: ViewModifier {
let menu: NSMenu
func body(content: Content) -> some View {
Interaction_UI(
view: { content },
menu: menu
)
.fixedSize()
}
}
private struct Interaction_UI<Content: View>: NSViewRepresentable {
typealias NSViewType = NSView
@ViewBuilder var view: Content
let menu: NSMenu
func makeNSView(context: Context) -> NSView {
let v = NSHostingController(rootView: view)
// option A - no effect
v.view.menu = menu
// option B - crash
v.menu = menu
return v.view
}
func updateNSView(_ nsView: NSViewType, context: Context) {
// part of option A
nsView.menu = menu
}
}
A classe de visualização para
NSHostingController
pode ter substituídomenu(for:)
ou amenu
propriedade, ou pode ter sido definidamenu
para outra coisa (para implementar SwiftUI,.contextMenu { ... }
por exemplo) depois que você a definiu. Afinal, diferente do UIKit, onde menus de contexto são adicionados aointeractions
array, há apenas uma únicamenu
propriedade para definir emNSView
.Sugiro subclassificar
NSHostingView
e substituirmenu(for:)
para retornar sua própriaNSMenu
propriedade.Então
NSViewRepresentable
pode ser escrito assim:Aqui está um exemplo mínimo que produz um menu ao clicar com o botão direito:
Na realidade, você provavelmente manteria o
NSMenu
em um@Observable
/ObservableObject
que pode responder às ações dos itens do menu. Essa classe também pode ser o . do menudelegate
.