-
[SwiftUI] DragGestureiOS 2023. 8. 4. 14:17
DragGesture() .updating($translation){ value, state, _ in print("๐state (ํ์ฌ ์ํ) ", state, " ๐value.translation.height (์ ๋ฐ์ดํธ ๋ ์ํ)", value.translation.height) state = translation } }DragGesture๋ ๋๋๊ทธ ์ด๋ฒคํธ ์ํ์ค๊ฐ ๋ณ๊ฒฝ๋ ๋ ์ก์ ์ ํธ์ถํ๋ ๋๋๊ทธ ๋ชจ์ ์ด๋ค.
๋ทฐ์์ ๋๋๊ทธ ์ ์ค์ฒ๋ฅผ ์ธ์ํ๋ ค๋ฉด ์ ์ค์ฒ๋ฅผ ๋ง๋ค๊ณ ๊ตฌ์ฑํ ๋ค์, gesture(_:including:) ๋ชจ๋ํ์ด์ด๋ฅผ ์ฌ์ฉํด์ ๋ทฐ์ ์ถ๊ฐํ๋ค.
๋ค์์ ์์ ๋๋๊ทธ ์ ์ค์ฒ๋ฅผ ์ถ๊ฐํ๊ณ , ์ฌ์ฉ์๊ฐ ๋๋๊ทธ ์ ์ค์ฒ๋ฅผ ์ํํ๋ ๋์ ์์ ์์์ ๋ณ๊ฒฝํ๋ ์ฝ๋๋ค.
struct DragGestureView: View { @State private var isDragging = false var drag: some Gesture { DragGesture() .onChanged { _ in self.isDragging = true } .onEnded { _ in self.isDragging = false } } var body: some View { Circle() .fill(self.isDragging ? Color.red : Color.blue) .frame(width: 100, height: 100, alignment: .center) .gesture(drag) } }init(minimumDistance: CGFloat, coordinateSpace: CoordinateSpace)์ ์ค์ฒ๊ฐ ์ฑ๊ณตํ๊ธฐ๊น์ง ์ต์ ๋๋๊ทธ ๊ฑฐ๋ฆฌ์ ์ ์ค์ฒ ์์น์ ์ขํ ๊ณต๊ฐ์ ์ฌ์ฉํด์ ๋๋๊ทธ ์ ์ค์ฒ๋ฅผ ์์ฑํ๋ค.
minimumDistance๋ ์ ์ค์ฒ๊ฐ ์ฑ๊ณตํ๊ธฐ ์ ์ ์ต์ ๋๋๊ทธ ๊ฑฐ๋ฆฌ,coordinateSpace๋ ์์น ๊ฐ์ ์์ ํ ์ขํ ๊ณต๊ฐ์ด๋ค.updating(_:body:)
์ ์ค์ฒ์ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ์ ๊ณต๋ ์ ์ค์ฒ ์ํ (state) ํ๋กํผํฐ๋ฅผ ์ ๋ฐ์ดํธํ๋ค.
func updating<State>( _ state: GestureState<State>, body: @escaping (Self.Value, inout State, inout Transaction) -> Void ) -> GestureStateGesture<Self, State>state๋ ๋ทฐ์ GestureState ํ๋กํผํฐ์ ๋ํ ๋ฐ์ธ๋ฉ์ด๊ณ , body๋ gesture์ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋ SwiftUI๊ฐ ํธ์ถํ๋ ์ฝ๋ฐฑ์ด๋ค.
body์ ํด๋ก์ ํ์ ์ (Self.Value, inout State, inout Transaction) -> Void์ด๋ค.
์ฌ๊ธฐ์ Self.Value๋ currentState ๋งค๊ฐ๋ณ์๋ก, ์ ์ค์ฒ์ ์ ๋ฐ์ดํธ๋ ์ํ๋ฅผ ์๋ฏธํ๋ค.
inout State๋ gestureState ๋งค๊ฐ๋ณ์๋ก, ์ ์ค์ฒ์ ์ด์ ์ํ๋ฅผ ์๋ฏธํ๋ค.
inout Transaction์ transaction์ ์๋ฏธํ๊ณ , ์ ์ค์ฒ์ ์ปจํ ์คํธ๋ฅผ ์๋ฏธํ๋ค.
์ด ๋ฉ์๋๋ ๊ธฐ์กด์ ์ ์ค์ฒ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ์ ์ค์ฒ์ ์ํ๋ฅผ ์ ๋ฐ์ดํธํ๋ค.
๋๋ ์ฌ์ฉ์๋ ์์คํ ์ด ์ ์ค์ฒ๋ฅผ ์ข ๋ฃํ๊ฑฐ๋ ์ทจ์ํ๋ฉด ์ ์ค์ฒ ๊ฐ์ ์ด๊ธฐ๊ฐ์ผ๋ก ์ฌ์ค์ ํ๋ค.
์๋ฅผ ๋ค์ด ์ฌ์ฉ์๊ฐ ๋ค์๊ณผ ๊ฐ์ด ํ๋ฉด์ ์์ฃผ ์งง์ ์๊ฐ ๋์ ์์์ ์๋๋ก ์๊ฐ๋ฝ์ ํฐ์นํ๋ ์ก์ ์ ์ทจํ๋ค๊ณ ๊ฐ์ ํ์.

์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋ค.
DragGesture() .updating($translation) { currentState, gestureState, _ in print("๐gestureState (์ด์ ์ํ)", gestureState, " ๐currentState (์ ๋ฐ์ดํธ๋ ์ํ)", currentState.translation.height) gestureState = currentState.translation.height // ์ํ ์ ๋ฐ์ดํธ } }์ด ๋ updating(_:body:) ๋ฉ์๋ ๋ด๋ถ์์๋ ๋ค์๊ณผ ๊ฐ์ ์ผ์ด ์ผ์ด๋๋ค.

์ต์ด state๋ 0.0์ด๊ณ , ์ฌ์ฉ์๊ฐ ์ ์ค์ฒ๋ฅผ ์ทจํ์ ์ํ๊ฐ ์ ๋ฐ์ดํธ๋์ด์ currentState๊ฐ ์ ๋ฐ์ดํธ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด์ ์ํ๋ฅผ ์๋ก์ด ์ํ๋ก ์ ๋ฐ์ดํธํด์ฃผ๊ธฐ ๋๋ฌธ์ gestureState๋ currentState๋ก ์ ๋ฐ์ดํธ๋๋ค.
์ด์ด์ ๋ currentState๊ฐ ์ ๋ฐ์ดํธ๋๋ฏ๋ก gestureState ๋ํ ์๋ก์ด ๊ฐ์ผ๋ก ์ ๋ฐ์ดํธ๋๋ค.
Respond to gesture callbacks
์ ์ค์ฒ ๋ชจ๋ํ์ด์ด์ ์ถ๊ฐํ ์ฝ๋ฐฑ์ ๋ฐ๋ผ, ์ ์ค์ฒ์ state๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค SwiftUI๊ฐ ์ฝ๋์ ๋ค์ ๋ณด๊ณ ๋ฅผ ํ๋ค. ์ ์ค์ฒ ๋ชจ๋ํ์ด์ด๋ ์ ๋ฐ์ดํธ๋ฅผ ์์ ํ๊ธฐ ์ํด 3๊ฐ์ง ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ค:
update(_:body:),onChanged(_:),onEnded(_:)Update transient UI state (์ผ์์ ์ธ UI ์ํ ์ ๋ฐ์ดํธ)
์ ์ค์ฒ๊ฐ ๋ณ๊ฒฝ๋ ๋ ๋ทฐ๋ฅผ ์ ๋ฐ์ดํธํ๋ ค๋ฉด, ๋ทฐ์ GestureState ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ๊ณ
update(_:body:)์ฝ๋ฐฑ์์ ์ ๋ฐ์ดํธํ๋ค. SwiftUI๋ ์ ์ค์ฒ๋ฅผ ์ธ์ํ๋ ์ฆ์, ๊ทธ๋ฆฌ๊ณ ์ ์ค์ฒ์ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์ ๋ฐ์ดํธ ์ฝ๋ฐฑ์ ํธ์ถํ๋ค.์๋ฅผ ๋ค์ด SwiftUI๋ magnification ์ ์ค์ฒ๊ฐ ์์๋์๋ง์ ์ ๋ฐ์ดํธ ์ฝ๋ฐฑ์ ํธ์ถํ๊ณ , ๋ค์ magnification ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ๋ค์ ์ ๋ฐ์ดํธ ์ฝ๋ฐฑ์ ํธ์ถํ๋ค. ์ฌ์ฉ์๊ฐ ์ ์ค์ฒ๋ฅผ ์ข ๋ฃํ๊ฑฐ๋ ์ทจ์ํ ๋์๋ ์ ๋ฐ์ดํธ ์ฝ๋ฐฑ์ ํธ์ถํ์ง ์๋๋ค. ๋์ , GestureState ํ๋กํผํฐ๊ฐ ์๋์ผ๋ก state ๊ฐ์ ์ด๊ธฐ๊ฐ์ผ๋ก ์ฌ์ค์ ํ๋ค.
์๋ฅผ ๋ค์ด ์ฌ์ฉ์๊ฐ ๊ธธ๊ฒ ๋๋ฅด๋ ๋์ ์์์ด ๋ณ๊ฒฝ๋๋ ๋ทฐ๋ฅผ ๋ง๋ค๊ธฐ ์ํด์๋ GestureState ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ๊ณ ์ ๋ฐ์ดํธ ์ฝ๋ฐฑ์์ ์ ๋ฐ์ดํธํ๋ฉด ๋๋ค.
struct CounterView: View { @GestureState private var isDetectingLongPress = false var body: some View { let press = LongPressGesture(minimumDuration: 1) .updating($isDetectingLongPress) { currentState, gestureState, transaction in // gestureState๋ฅผ ์๋ก์ด ๊ฐ์ผ๋ก ์ ๋ฐ์ดํธ gestureState = currentState } return Circle() .fill(isDetectingLongPress ? Color.yellow : Color.green) .frame(width: 100, height: 100, alignment: .center) .gesture(press) } }
Update permanent state during a gesture (์๊ตฌ์ ์ธ UI ์ํ ์ ๋ฐ์ดํธ)
์ ์ค์ฒ๊ฐ ์ข ๋ฃ๋์ด๋ ์ฌ์ค์ ๋์ง ์๋ ์ ์ค์ฒ์ ๋ณ๊ฒฝ ์ฌํญ์ ์ถ์ ํ๋ ค๋ฉด,
onChanged(_:)์ฝ๋ฐฑ์ ์ฌ์ฉํ๋ค.์๋ฅผ ๋ค์ด, ์ฑ์์ ๊ธธ๊ฒ ๋๋ฅด๋ ๋์์ ์ธ์ํ๋ ํ์๋ฅผ ๊ณ์ฐํ๋ ค๋ฉด
onChanged(_:)์ฝ๋ฐฑ์ ์ถ๊ฐํ๊ณ ์นด์ดํฐ๋ฅผ ์ฆ๊ฐ์ํค๋ฉด ๋๋ค.struct CounterView: View { @GestureState private var isDetectingLongPress = false @State private var totalNumberOfTaps = 0 var body: some View { let press = LongPressGesture(minimumDuration: 1) .updating($isDetectingLongPress) { currentState, gestureState, transaction in gestureState = currentState }.onChanged { _ in self.totalNumberOfTaps += 1 } return VStack { Text("\(totalNumberOfTaps)") .font(.largeTitle) Circle() .fill(isDetectingLongPress ? Color.yellow : Color.green) .frame(width: 100, height: 100, alignment: .center) .gesture(press) } } }
Update permanent state when a gesture ends (์ ์ค์ฒ๊ฐ ์ข ๋ฃ๋ ๋ ์๊ตฌ์ ์ผ๋ก ์ํ ์ ๋ฐ์ดํธ)
์ ์ค์ฒ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋ ์์ ์ ์ธ์งํ๊ณ ์ ์ค์ฒ์ ์ต์ข ๊ฐ์ ๋ฐ์ผ๋ ค๋ฉด,
onEnded(_:)ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๋ฐฑ์์ ์ฑ์ ์ํ๋ฅผ ์ ๋ฐ์ดํธํ๋ค. SwiftUI๋ ์ ์ค์ฒ๊ฐ ์ฑ๊ณตํ ๋๋งonEnded(_:)์ฝ๋ฐฑ์ ํธ์ถํ๋ค.์๋ฅผ ๋ค์ด, LongPressGesture ๋์ค์ ์ฌ์ฉ์๊ฐ minimumDuration ์ด๊ฐ ๊ฒฝ๊ณผํ๊ธฐ ์ ์ ๋ทฐ ํฐ์น๋ฅผ ๋ฉ์ถ๊ฑฐ๋, maximumDistance๋ณด๋ค ๋ ๋ง์ด ์๊ฐ๋ฝ์ ์์ง์ด๋ฉด, SwiftUI๋
onEnded(_:)์ฝ๋ฐฑ์ ํธ์ถํ์ง ์๋๋ค. ์ฆ, minimumDuration ์ด๋ฅผ ๋์ด์ ๋ทฐ ํฐ์น๋ฅผ ์งํํ๊ณ , maximumDistance๋ฅผ ๋์ด์ ์๊ฐ๋ฝ์ ์์ง์ด์ง ์๋ ๊ฒฝ์ฐ์๋งonEnded(_:)์ฝ๋ฐฑ์ ํธ์ถํ๋ค.์๋ฅผ ๋ค์ด ์ฌ์ฉ์๊ฐ long press๋ฅผ ์๋ฃํ ํ long press ์๋ ํ์ ๊ณ์ฐ์ ์ค์งํ๋ ค๋ฉด,
onEnded(_:)์ฝ๋ฐฑ์ ์ถ๊ฐํ๊ณ ์ ์ค์ฒ ๋ชจ๋ํ์ด์ด๋ฅผ ์กฐ๊ฑด๋ถ๋ก ์ถ๊ฐํ๋ฉด ๋๋ค.struct CounterView: View { @GestureState private var isDetectingLongPress = false @State private var totalNumberOfTaps = 0 @State private var doneCounting = false var body: some View { let press = LongPressGesture(minimumDuration: 1) .updating($isDetectingLongPress) { currentState, gestureState, transaction in gestureState = currentState }.onChanged { _ in self.totalNumberOfTaps += 1 } .onEnded { _ in self.doneCounting = true } return VStack { Text("\(totalNumberOfTaps)") .font(.largeTitle) Circle() .fill(doneCounting ? Color.red : isDetectingLongPress ? Color.yellow : Color.green) .frame(width: 100, height: 100, alignment: .center) .gesture(doneCounting ? nil : press) } } }
https://developer.apple.com/documentation/swiftui/draggesture
Adding interactivity with gestures | Apple Developer Documentation
'iOS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[SwiftUI] ๋๋ฐ์ด์ค์ width, height ๊ตฌํ๊ธฐ (0) 2023.08.03 [iOS] Cocoapods ์ค์น ๋ฐ ์ฌ์ฉ๋ฒ (0) 2023.05.30 [iOS] Compiling for iOS 11.0, but module 'ComposableArchitecture' has a minimum deployment target of iOS 13.0 ์ค๋ฅ ํด๊ฒฐ (0) 2023.05.17 [iOS] Swift Package Manager (SPM) ์์ฑํ๊ธฐ (0) 2023.05.16 [iOS] Swift Package Manager (SPM) (0) 2023.05.11