I'm writing a simple Mines app to help me get to know SwiftUI. As such, I want primary click (usually LMB) to "dig" (reveal whether there's a mine there), and secondary click (usually RMB) to place a flag.
I have the digging working! But I can't figure out how to place a flag, because I can't figure out how to detect a secondary click.
BoardSquareView(
style: self.style(for: square),
model: square
)
.gesture(TapGesture().modifiers(.control).onEnded(self.handleUserDidAltTap(square)))
.gesture(TapGesture().onEnded(self.handleUserDidTap(square)))
As I implied earlier, the function returned by handleUserDidTap
is called properly on click, but the one returned by handleUserDidAltTap
is only called when I hold down the Control key. That makes sense because that's what the code says... but I don't see any API which could make it register secondary clicks, so I don't know what else to do.
I also tried this, but the behavior seemed identical:
BoardSquareView(
style: self.style(for: square),
model: square
)
.gesture(TapGesture().modifiers(.control).onEnded(self.handleUserDidAltTap(square)))
.onTapGesture(self.handleUserDidTap(square))
As things stand with SwiftUI right now, this isn't directly possible. I am sure it will be in the future, but at the moment, the TapGesture
is clearly focused mainly on the iOS use cases which don't have a concept of a "right click" so I think that is why this was ignored. Notice the "long press" concept is a first-class citizen in the form of the LongPressGesture
, and that is almost exclusively used in an iOS context, which supports this theory.
That said, I did figure out a way to make this work. What you have to do is fall back on the older technology, and embed it into your SwiftUI view.
struct RightClickableSwiftUIView: NSViewRepresentable {
func updateNSView(_ nsView: RightClickableView, context: NSViewRepresentableContext<RightClickableSwiftUIView>) {
print("Update")
}
func makeNSView(context: Context) -> RightClickableView {
RightClickableView()
}
}
class RightClickableView: NSView {
override func mouseDown(with theEvent: NSEvent) {
print("left mouse")
}
override func rightMouseDown(with theEvent: NSEvent) {
print("right mouse")
}
}
I tested this, and it worked for me inside a fairly complex SwiftUI application. The basic approach here is:
NSView
.NSViewRepresentable
.Not an ideal solution, but it might be good enough for right now. I hope this solves your problem until Apple expands SwiftUI's capabilities further.