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 功能总结
- 专为手势设计,状态管理自动化。
- 更适合短暂的、与手势操作相关的状态。
- 自动处理中断和复位。
- 更方便的设置动画。