はじめに
SwiftUIで、Gestureを使ったUIを作成する機会があり、その時の実装メモを残したいと思います。
どんなことをするのか
Viewをロングタップして、その場所(座標)をView側に伝える
概論
SwiftUIだけでは完結しなかった。
UIViewRepresentableを使って、UIKitのGestureを使う必要がある(iOS14までだと多分、)
実際のコード
早速実際のコードです
UIViewRepresentableを使ったところ
ViewRepresentable.swift
struct ViewRepresentable: UIViewRepresentable {
class Coordinator: NSObject {
@Binding var point: CGPoint
init(point: Binding<CGPoint>) {
_point = point
}
@objc func longTapped(_ gesture: UILongPressGestureRecognizer) {
// stateは適当なイベントで、
if gesture.state == .began {
point = gesture.location(in: gesture.view)
}
}
}
/// タップされた座標
@Binding var point: CGPoint
func makeUIView(context: Context) -> UIView {
let view = UIView(frame: .zero)
let gesture = UILongPressGestureRecognizer(
target: context.coordinator,
action: #selector(Coordinator.longTapped(_:))
)
view.addGestureRecognizer(gesture)
return view
}
func makeCoordinator() -> ViewRepresentable.Coordinator {
Coordinator(point: $point)
}
func updateUIView(_ uiView: UIView, context: Context) {}
}
あとはこれを適当なViewに当てはめれば、OKです
ContentView.swift
struct ContentView: View {
@State private var point: CGPoint = .zero
var body: some View {
ViewRepresentable(point: $point)
.frame(width: UIScreen.main.bounds.width,
height: UIScreen.main.bounds.height)
}
}
以上です。
これでContentViewでロングタップされた座標を取ることができるようになりました
ちなみに、ロングタップされて動いた時の座標は、UIGestureRecognizerのstateを変更すれば取得できます
ViewRepresentable.swift
@objc func longTapped(_ gesture: UILongPressGestureRecognizer) {
// .changedに変更
if gesture.state == .changed {
point = gesture.location(in: gesture.view)
}
}
参考