Xcode: 12.4, Swift: 5
SwiftUIのViewにおいて、作成したオブジェクトをドラッグし、そのドラッグ後の座標をリアルタイムに表示する方法を紹介します。ポイントとなるキーワードは以下のとおりです。
- @State
- .gesture
- onChanged
1. オブジェクトを作成(ここではCircle)
[ads]
import SwiftUI
struct Sample: View {
var body: some View {
Circle()
.fill(Color.blue)
.frame(width: 80, height: 80)
}
}

特に指定していないため、画面中央に表示される。
2. @State変数を追加
[ads]
import SwiftUI
struct Sample: View {
@State private var location: CGPoint = CGPoint(x: 0, y: 0)
var body: some View {
VStack {
Circle()
.fill(Color.blue)
.frame(width: 80, height: 80)
.position(location)
}
}
}

.positionモディファイアを使用し、@State変数にバインディングすることで、この@State変数であるlocationの変化にサークルオブジェクトが追従するようになります。
3. 座標表示用のテキストボックス追加
[ads]
import SwiftUI
struct Sample: View {
@State private var location: CGPoint = CGPoint(x: 0, y: 0)
var body: some View {
VStack {
Text("x: \(location.x)")
Text("y: \(location.y)")
Circle()
.fill(Color.blue)
.frame(width: 80, height: 80)
.position(location)
}
}
}

座標表示用のテキストボックスを追加。
VStackで追加しているため、サークルの座標は(0, 0)のままだが、テキストボックスの分下方向にずれています。
4. gestureモディファイアを追加
[ads]
.gestureを追加することで、ジェスチャーを認識することができる。その一つである、onChangedイベントを利用する。Closureを用いて、このサークルオブジェクトのpositionモディファイアにバインディングされているlocation変数を、現在の座標で都度更新するような動作。
import SwiftUI
struct Sample: View {
@State private var location: CGPoint = CGPoint(x: 0, y: 0)
var body: some View {
VStack {
Text("x: \(location.x)")
Text("y: \(location.y)")
Circle()
.fill(Color.blue)
.frame(width: 80, height: 80)
.position(location)
.gesture(DragGesture().onChanged({ value in self.location = value.location}))
}
}
}

Live Previewにすることで、ドラッグイベントの変化が@State変数のlocationにリアルタイムに更新され、その値が同時にリアルタイムにテキストボックスに表示されるようになります

