> For the complete documentation index, see [llms.txt](https://lochiwei.gitbook.io/ios/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lochiwei.gitbook.io/ios/swiftui/gestures.md).

# Gestures

[SwiftUI](/ios/swiftui.md) ⟩ [Gestures](/ios/swiftui/gestures.md) ⟩&#x20;

{% tabs %}
{% tab title="⭐️ 重點" %}
{% hint style="info" %}
⭐️ [**`.updating()`**](https://developer.apple.com/documentation/swiftui/gesture/updating\(_:body:\))

update [gesture states](/ios/swiftui/gestures/gesturestate.md) (fires as soon as it <mark style="color:orange;">**recognizes**</mark> the gesture and whenever the <mark style="color:orange;">**value of the gesture changes**</mark>. )
{% endhint %}

{% hint style="success" %}
⭐️ [**`.onChanged()`**](https://developer.apple.com/documentation/swiftui/gesture/onchanged\(_:\))

updates <mark style="color:orange;">**permanent view state**</mark> whenever the <mark style="color:orange;">**value of the gesture changes**</mark>.
{% endhint %}

{% hint style="success" %}
⭐️ [**`.onEnded()`**](https://developer.apple.com/documentation/swiftui/gesture/onended\(_:\))

updates <mark style="color:orange;">**permanent view state**</mark> when gesture <mark style="color:red;">**successfully**</mark> ends. (fires when a gesture <mark style="color:red;">**successfully completes**</mark> and receives its <mark style="color:red;">**final value**</mark>.)
{% endhint %}
{% endtab %}

{% tab title="🔴 主題" %}

* [update gesture states](/ios/swiftui/gestures/update-gesture-states.md) - [.updating()](https://developer.apple.com/documentation/swiftui/gesture/updating\(_:body:\))
* [update view states](/ios/swiftui/gestures/update-view-states.md) - [.onChanged()](https://developer.apple.com/documentation/swiftui/gesture/onchanged\(_:\)), [.onEnded()](https://developer.apple.com/documentation/swiftui/gesture/onended\(_:\))
* [GestureState](/ios/swiftui/gestures/gesturestate.md) - transient gesture states
* [Long Press](/ios/swiftui/gestures/long-press.md)
* [Drag](/ios/swiftui/gestures/drag.md)
* [Combining Gestures](/ios/swiftui/gestures/combine.md)
  * [.sequenced()](/ios/swiftui/gestures/combine/sequenced.md)
    {% endtab %}

{% tab title="💾 程式" %}
{% embed url="<https://youtu.be/giJ88vudR48>" %}

📗 參考：[Adding Interactivity with Gestures](https://developer.apple.com/documentation/swiftui/adding-interactivity-with-gestures) ⭐️

⬆️ 需要： [TimerView](/ios/swift/scope/framework/built-in-frameworks/combine/timer/timerview.md) (for countdown)

```swift
struct ContentView: View {
    
    // ⭐️ gesture state is "transient"
    //   (reset to initial value when gesture ends or cancelled)
    @GestureState var isPressing = false
    
    // ⭐️ view states are "permanent" (won't reset)
    @State private var tapCount = 0
    @State private var longPressCount = 0
    @State private var isCounting = true
    
    /// long press
    var longPress: some Gesture {
        
        LongPressGesture(minimumDuration: 3)    // for 3 sec
            
            // ⭐️ update gesture state (while pressing)
            .updating($isPressing) { value, state, _ in
                state = value
            }
            
            // ⭐️ update view state (when tap/press is detected)
            // ❗️ 注意：這是「摸到」就會觸發，不是「長按」才會觸發。
            // 🔸 [註] 官網上寫：
            //        count the number of times your app recognizes a "long press"
            //    是錯誤的，應該是：
            //        ... recognizes a "tap"❗️
            .onChanged { _ in
                tapCount += 1
            }
            
            // ⭐️ update view states when gesture (successfully) ends.
            .onEnded { _ in
                isCounting = false
                longPressCount += 1
            }
    }
    
    var body: some View {
        VStack {
            Text("tap count: \(tapCount)")
            Text("long press count: \(longPressCount)")
            Circle()
                .fill(isPressing ? .pink : .green)
                .frame(width: 100, height: 100, alignment: .center)
                
                // ⭐️ apply gesture if is counting taps
                .gesture(isCounting ? longPress : nil)
                
                .overlay {
                    if isPressing {
                        // ⭐️ count-down timer
                        TimerView(seconds: 3) { sec in
                            Text("\(sec)").font(.system(size: 50)).bold()
                        }   // 👔 TimeView
                    }
                }
            
            // optional view
            if !isCounting {
                Text("long press gesture disabled\nsorry, no more taps.")
                    .font(.caption)
                    .foregroundColor(.secondary)
            }
        }
    }
}
```

{% endtab %}

{% tab title="📗 參考" %}

* [ ] [Mastering SwiftUI](https://www.appcoda.com/swiftui/), Ch. 17: Using Gestures
* [ ] [SwiftUI](https://developer.apple.com/documentation/swiftui) ⟩ [Gestures](https://developer.apple.com/documentation/swiftui/gestures) ⟩&#x20;
  * [x] [Adding Interactivity with Gestures](https://developer.apple.com/documentation/swiftui/adding-interactivity-with-gestures) ⭐️
  * [ ] [Composing SwiftUI Gestures](https://developer.apple.com/documentation/swiftui/composing-swiftui-gestures)
    {% endtab %}

{% tab title="📘 手冊" %}

* [SwiftUI](https://developer.apple.com/documentation/swiftui) ⟩&#x20;
  * [Gestures](https://developer.apple.com/documentation/swiftui/gestures) ⟩ [Gesture](https://developer.apple.com/documentation/swiftui/gesture) (<mark style="color:orange;">**protocol**</mark>)
    * [.updating(\_:body:)](https://developer.apple.com/documentation/swiftui/gesture/updating\(_:body:\)) - <mark style="color:red;">**update gesture state**</mark> as gesture’s value changes.
    * [.onChanged(\_:)](https://developer.apple.com/documentation/swiftui/gesture/onchanged\(_:\)) - <mark style="color:red;">**perform an action**</mark> when gesture’s value changes.
    * [.onEnded(\_:)](https://developer.apple.com/documentation/swiftui/gesture/onended\(_:\))
  * [Input and Event Modifiers](https://developer.apple.com/documentation/swiftui/view-input-and-events) ⟩ [.gesture(\_:including:)](https://developer.apple.com/documentation/swiftui/view/gesture\(_:including:\))
    {% endtab %}

{% tab title="❓" %}
{% hint style="success" %}
問：「 [.updating()](https://developer.apple.com/documentation/swiftui/gesture/updating\(_:body:\)) 與 [.onChanged()](https://developer.apple.com/documentation/swiftui/gesture/onchanged\(_:\)) 到底有什麼差別❓」

答：「 [.updating()](https://developer.apple.com/documentation/swiftui/gesture/updating\(_:body:\)) 更新 gesture states，[.onChanged()](https://developer.apple.com/documentation/swiftui/gesture/onchanged\(_:\)) 更新 view states。」
{% endhint %}
{% endtab %}
{% endtabs %}
