如何让父方法等待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
相关产品推荐
相关产品推荐

