I've tried to adapt a solution I've used on an iOS app to macOS using NSViewRepresentable instead of UIViewRepresentable.
Below is my 'Tappable View'. My problem is that when I try to use this view I get the error Cannot find "TappableView" in scope
.
Thanks.
(using Xcode Version 12.0 beta 4)
import Foundation
import SwiftUI
struct TappableView: NSViewRepresentable {
var tappedCallback: ((CGPoint, Int) -> Void)
func makeNSView(context: NSViewRepresentableContext<TappableView>) -> NSView {
let v = UIView(frame: .zero)
let gesture = NSClickGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.tapped))
gesture.numberOfTapsRequired = 1
let gesture2 = NSClickGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.doubleTapped))
gesture2.numberOfTapsRequired = 2
gesture.require(toFail: gesture2)
v.addGestureRecognizer(gesture)
v.addGestureRecognizer(gesture2)
return v
}
class Coordinator: NSObject {
var tappedCallback: ((CGPoint, Int) -> Void)
init(tappedCallback: @escaping ((CGPoint, Int) -> Void)) {
self.tappedCallback = tappedCallback
}
@objc func tapped(gesture:NSClickGestureRecognizer) {
let point = gesture.location(in: gesture.view)
self.tappedCallback(point, 1)
}
@objc func doubleTapped(gesture:NSClickGestureRecognizer) {
let point = gesture.location(in: gesture.view)
self.tappedCallback(point, 2)
}
}
func makeCoordinator() -> TappableView.Coordinator {
return Coordinator(tappedCallback:self.tappedCallback)
}
func updateNSView(_ nsView: NSView, context: NSViewRepresentableContext<TappableView>) {
}
}
Here is working variant
struct TappableView: NSViewRepresentable {
var tappedCallback: ((CGPoint, Int) -> Void)
func makeNSView(context: NSViewRepresentableContext<TappableView>) -> NSView {
let v = NSView(frame: .zero)
context.coordinator.configure(view: v)
return v
}
class Coordinator: NSObject, NSGestureRecognizerDelegate {
var tappedCallback: ((CGPoint, Int) -> Void)
private var gesture: NSClickGestureRecognizer!
private var gesture2: NSClickGestureRecognizer!
init(tappedCallback: @escaping ((CGPoint, Int) -> Void)) {
self.tappedCallback = tappedCallback
}
func configure(view: NSView) {
gesture = NSClickGestureRecognizer(target: self, action: #selector(Coordinator.tapped))
gesture.delegate = self
gesture.numberOfClicksRequired = 1
gesture2 = NSClickGestureRecognizer(target: self, action: #selector(Coordinator.doubleTapped))
gesture2.delegate = self
gesture2.numberOfClicksRequired = 2
view.addGestureRecognizer(gesture)
view.addGestureRecognizer(gesture2)
}
@objc func tapped(gesture:NSClickGestureRecognizer) {
let point = gesture.location(in: gesture.view)
self.tappedCallback(point, 1)
}
@objc func doubleTapped(gesture:NSClickGestureRecognizer) {
let point = gesture.location(in: gesture.view)
self.tappedCallback(point, 2)
}
func gestureRecognizer(_ gestureRecognizer: NSGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: NSGestureRecognizer) -> Bool {
return gestureRecognizer === gesture && otherGestureRecognizer === gesture2
}
}
func makeCoordinator() -> TappableView.Coordinator {
return Coordinator(tappedCallback:self.tappedCallback)
}
func updateNSView(_ nsView: NSView, context: NSViewRepresentableContext<TappableView>) {
}
}