You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中如何随时取消带延迟的withAnimation动画?

实现可取消的延迟动画任务

要实现支持随时取消的延迟动画,你需要用Swift的Task替代原来的DispatchQueue.main.asyncAfter——Task原生支持取消操作,能更方便地控制任务生命周期。以下是完整实现方案:

核心实现代码

import SwiftUI

struct ContentView: View {
    @State private var opacity: Double = 1.0
    // 持有任务引用,用于后续取消操作
    @State private var delayedAnimationTask: Task<Void, Never>?
    
    var body: some View {
        VStack(spacing: 30) {
            // 演示动画的视图
            Rectangle()
                .fill(.blue)
                .opacity(opacity)
                .frame(width: 200, height: 200)
            
            HStack(spacing: 20) {
                Button("启动任务") {
                    startDelayedAnimation()
                }
                
                Button("取消任务") {
                    cancelAnimationTask()
                }
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()
    }
    
    // 启动延迟动画任务
    private func startDelayedAnimation() {
        // 先清理旧任务,避免多个任务冲突
        cancelAnimationTask()
        
        delayedAnimationTask = Task {
            do {
                // 等待5秒(转换为纳秒)
                try await Task.sleep(nanoseconds: 5_000_000_000)
                
                // 检查任务是否已取消,取消则终止后续操作
                guard !Task.isCancelled else { return }
                
                // 执行3秒动画,将opacity设为0
                withAnimation(.easeInOut(duration: 3)) {
                    opacity = 0.0
                }
            } catch {
                // 任务被取消时会抛出CancellationError,这里无需额外处理
            }
        }
    }
    
    // 取消任务并重置状态
    private func cancelAnimationTask() {
        delayedAnimationTask?.cancel()
        opacity = 1.0
        delayedAnimationTask = nil
    }
}

#Preview {
    ContentView()
}

关键细节说明

  • 任务持有与管理:用@State private var delayedAnimationTask: Task<Void, Never>?保存任务引用,这样能在任意时刻调用cancel()终止任务。
  • 取消逻辑:调用cancelAnimationTask()时,会立即终止任务(无论处于等待5秒还是动画执行阶段),同时将opacity重置为1。
  • 任务冲突避免:启动新任务前先调用cancelAnimationTask(),确保同一时间只有一个任务在运行,防止状态混乱。
  • 取消检查:在等待5秒结束后,额外检查Task.isCancelled,避免任务在等待期间被取消后仍执行动画。

内容的提问来源于stack exchange,提问作者Gregor Sotošek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 01:50:00