如何优化SwiftUI中Sheet展示延迟,替代变量赋值延迟实现单元格选中动画?
优化方案:移除硬编码延迟,原生监听动画完成
当前通过DispatchQueue.main.asyncAfter硬编码延迟的方式存在明显缺陷:固定的延迟时间无法适配不同设备的动画执行速度,且不符合SwiftUI的原生动画逻辑。以下是两种更优雅的实现方式:
方式一:利用withAnimation完成回调(iOS 15+)
iOS 15及以上版本的SwiftUI提供了带完成回调的withAnimation方法,可以精准监听选中动画结束,再触发Sheet展示:
修改点击手势代码:
.onTapGesture { withAnimation(.easeOut) { selectedItem = expense } completion: { shouldPresentEditExpense = true } }
同时可以移除原代码中的.animation(.easeOut, value: selectedItem),因为动画逻辑已被withAnimation包裹。
方式二:监听动画事务状态(兼容iOS 13+)
如果需要兼容更低版本,可以通过监听事务的动画活跃状态来判断动画是否完成:
- 在视图中添加状态变量标记动画开始:
@State private var isSelectionAnimating = false
- 修改点击手势和状态监听逻辑:
.onTapGesture { isSelectionAnimating = true withAnimation(.easeOut) { selectedItem = expense } } .onChange(of: selectedItem) { _ in guard isSelectionAnimating else { return } let transaction = Transaction() // 当动画事务不再活跃时,说明动画已完成 if !transaction.animation.active { shouldPresentEditExpense = true isSelectionAnimating = false } }
额外优化:简化选中判断逻辑
你的ExpenseSelectableCell可以直接简化选中状态判断,无需单独写isSelected()方法:
struct ExpenseSelectableCell: ViewModifier { @Binding var selectedItem: Expense? let expense: Expense func body(content: Content) -> some View { content .overlay { Color.black.opacity(selectedItem?.id == expense.id ? 0.2 : 0) } } }
以上方案均能保证选中动画完整展示后再弹出Sheet,既避免了硬编码延迟的不确定性,又贴合SwiftUI的原生设计思想。
内容的提问来源于stack exchange,提问作者RafaSG13
相关产品推荐
相关产品推荐

