TL;DR:
@GestureState专为手势操作设计,能在手势中断时自动重置状态,适合短暂的、与手势相关的状态管理;而@State更通用,但需手动处理手势中断逻辑。
背景
@GestureState 是 SwiftUI 为手势操作设计的专属状态管理工具。在许多场景下,开发者可能发现使用 @State 也能完成类似的任务,那么苹果为何额外提供 @GestureState?本文将对两者进行比较,并探讨其适用场景与核心差异。
类似的表现
@GestureState 和 @State 都可以用于存储和更新状态,例如实现点击或拖拽等交互效果。
使用 @GestureState
以下代码展示了 @GestureState 的使用:
          Swift
          
        
      struct ContentView: View {
    @GestureState var isPressed = false
    var body: some View {
        Rectangle()
            .fill(.orange)
            .frame(width: 200, height: 200)
            .gesture(
                DragGesture(minimumDistance: 0)
                    .updating($isPressed) { _, state, _ in
                        state = true
                    }
            )
            .overlay(
                Text(isPressed ? "Pressing" : "")
            )
    }
}在此例中,@GestureState 在手势活动期间被更新为 true,当手势结束或被打断时,状态会自动重置为 false。
使用 @State
类似功能可以用 @State 实现:
          Swift
          
        
      struct ContentView: View {
    @State var isPressed = false
    var body: some View {
        Rectangle()
            .fill(.orange)
            .frame(width: 200, height: 200)
            .gesture(
                DragGesture(minimumDistance: 0)
                    .onChanged { _ in
                        isPressed = true
                    }
                    .onEnded { _ in
                        isPressed = false
                    }
            )
            .overlay(
                Text(isPressed ? "Pressing" : "")
            )
    }
}表面上看,这两种方法在功能上几乎相同。
核心区别
手势中断的处理是 @GestureState 与 @State 的关键差异所在。
手势中断场景
当手势被系统操作打断(例如下拉通知中心、启动应用切换手势但未完成等),onEnded 闭包将被忽略,导致无法执行  @State 的重置操作。而 @GestureState 会在这种情况下自动复位。
- @GestureState的表现: 状态会在手势中断时自动恢复到初始值,无需额外处理。
- @State的表现: 手势中断时,- onEnded不会被调用,状态保持手势最后的值,导致状态可能不准确。
示例对比
以下视频演示了手势中断时的行为差异:
- @GestureState:状态在中断后自动复位。
- @State:状态不会自动复位,需手动处理中断逻辑。
开发者也可以利用
@State不会在手势被打断时自动复位的特性来实现一些特殊的需求。
@GestureState 功能总结
- 专为手势设计,状态管理自动化。
- 更适合短暂的、与手势操作相关的状态。
- 自动处理中断和复位。
- 更方便的设置动画。
延伸阅读
"加入我们的 Discord 社区,与超过 2000 名苹果生态的中文开发者一起交流!"