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

如何让父方法等待UIView视图过渡动画完成后再执行后续逻辑

解决UIView动画完成前执行后续代码的问题

这个问题本质是因为UIView.animate是异步执行的——调用这个方法后,系统会把动画任务放到后台处理,主线程会立刻继续执行moveCard()之后的代码,完全不会等动画结束。我给你两种实用的解决方案,根据你的项目需求选择就行:

方案1:给moveCard添加完成回调闭包(兼容所有iOS版本)

这是最经典的回调式写法,不管你的项目最低支持哪个iOS版本都能用。我们只需要给moveCard方法加一个可选的完成闭包参数,在动画真正结束的时候调用这个闭包就行:

func moveCard(completion: (() -> Void)? = nil) -> Void{
    UIView.animate(withDuration: 5.0) {
        self.hhview.transform = CGAffineTransform(translationX: -160, y: 0)
    } completion: { _ in
        print("Move completed")
        // 动画完成后,调用传入的回调闭包
        completion?()
    }
}

然后在playerCheck里调用时,把需要等待动画完成的代码放到这个闭包里面:

func playerCheck() -> Void{
    // ... 你的其他前置代码
    moveCard {
        // 这里的所有代码都会等动画完成后才执行
        print("playerCheck continued")
        // 把原本写在moveCard()后面的代码都移到这里来
    }
}

方案2:用Async/Await(iOS 15.0+ 适用)

如果你的项目最低支持iOS 15或以上,用Swift的异步/等待语法会更优雅,代码逻辑更线性,不用嵌套闭包。我们可以把moveCard改成异步函数,利用withCheckedThrowingContinuation把回调式的动画转换成可等待的异步任务:

func moveCard() async -> Void{
    await withCheckedThrowingContinuation { continuation in
        UIView.animate(withDuration: 5.0) {
            self.hhview.transform = CGAffineTransform(translationX: -160, y: 0)
        } completion: { _ in
            print("Move completed")
            // 通知异步流程可以继续了
            continuation.resume()
        }
    }
}

然后把playerCheck也改成异步函数,用await关键字等待moveCard完成:

func playerCheck() async -> Void{
    // ... 你的其他前置代码
    await moveCard()
    // 这里的代码会自动等待动画完成后执行
    print("playerCheck continued")
}

注意:调用playerCheck的地方也需要用await,或者放在Task里面执行,比如:

// 在视图控制器的某个方法里调用
Task {
    await playerCheck()
}

两种方案都能完美解决你的问题,如果你需要兼容旧系统就选方案1,新项目直接用方案2更清爽~

内容的提问来源于stack exchange,提问作者SACHINTHANA WELIWATTAGE

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:12:30