在异步方法中使用 withAnimation
了解如何在 Swift 异步方法中,使用 withAnimation 添加更新动画,并理解为什么在某些情况下动画不生效。
在同步函数中使用 withAnimation
下面这个示例代码,使用同步编程的方式,调用 updateDisplayRecords()
更新displayRecords,并使用 LazyVStack
进行展示。
struct ExpenseListView: View {
// 定义属性
var body: some View {
if isLoading {
ProgressView()
.padding(.top, 50)
} else {
LazyVStack(spacing: 16) {
ForEach(displayRecords, id: \.id) { record in
RecordRowListView(
record: record, useMinuteFormat: false
)
.transition(.blurReplace)
}
}
.onChange(of: selectedCategoryFilter) {
updateDisplayRecords()
}
}
}
// 同步函数
private func updateDisplayRecords() {
withAnimation(.spring) {
displayRecords = filterRecords
}
}
// 同步函数
private func filterRecords() -> [Record] {
records.filter { record in
// 执行筛选计算
}
}
}
在 updateDisplayRecords()
中使用 withAnimation 为更新添加动画:
在异步中使用 withAnimation 无法生效
如果将 updateDisplayRecords()
修改为异步函数,并通过.task()
调用更新,那么 withAnimation 将不再生效:
struct ExpenseListView: View {
// 定义属性
var body: some View {
if isLoading {
ProgressView()
.padding(.top, 50)
} else {
LazyVStack(spacing: 16) {
ForEach(displayRecords, id: \.id) { record in
RecordRowListView(
record: record, useMinuteFormat: false
)
.transition(.blurReplace)
}
}
.task(id: selectedCategoryFilter) {
await updateDisplayRecords()
}
}
}
// 添加更新显示记录的异步函数
private func updateDisplayRecords() async {
// 先获取过滤后的数据
let filteredRecords = await filterRecords()
withAnimation(.spring) {
displayRecords = filteredRecords
}
}
// 将过滤逻辑改为异步函数
private func filterRecords() async -> [Record] {
records.filter { record in
// 执行筛选计算
}
}
}