我在下面的代码片段中将正方形动画化为圆形。我的视图观察
isCircle
属性来确定是绘制圆形还是方形。 MyData#doSomethingExpensive
方法旨在模拟一个长时间运行的任务,该任务完成后会触发 UI 进行动画处理(在本例中将正方形动画化为圆形)。
这实际上按预期工作,但我的
withAnimation
UI 模型中有一个 @Observable
调用。如果可能的话,我宁愿在视图内有 withAnimation
。我还想继续使用 @Observable
API,而不是切换回 ObservableObject
一致性。有没有办法重构它,以便视图能够使用与我在这里相同的动画来响应 isCircle
中的变化:
import SwiftUI
@Observable
final class MyData {
var isCircle = false
func doSomethingExpensive() {
Task {
try await Task.sleep(for: .milliseconds(Int.random(in: 300...800)))
withAnimation(.smooth(duration: 1.5)) {
self.isCircle.toggle()
}
}
}
}
struct ContentView: View {
let myData = MyData()
var body: some View {
VStack {
if myData.isCircle {
Circle().fill(.blue).frame(width: 200)
} else {
Rectangle().fill(.red).frame(width: 200, height: 200)
}
Button("Animate later") {
myData.doSomethingExpensive()
}
}
}
}
一种方法是,您可以将
Task{...}
移动到视图中,例如:
@Observable
final class MyData {
var isCircle = false
func doSomethingExpensive() async throws {
try await Task.sleep(for: .milliseconds(Int.random(in: 300...800))) // <--- here
}
}
struct ContentView: View {
let myData = MyData()
var body: some View {
VStack {
if myData.isCircle {
Circle().fill(.blue).frame(width: 200)
} else {
Rectangle().fill(.red).frame(width: 200, height: 200)
}
Button("Animate later") {
Task { // <--- here
try await myData.doSomethingExpensive()
withAnimation(.smooth(duration: 1.5)) {
myData.isCircle.toggle()
}
}
}
}
}
}