如何在SwiftUI的Button动作回调中强制触发视图立即重绘
你要实现的效果没办法通过「暂停其他任务强制重绘」实现,SwiftUI的所有UI更新逻辑都运行在主线程,你当前在Button的action回调里直接执行while循环+usleep的写法,已经把主线程完全阻塞了,期间所有状态变更、重绘请求都不会被执行,直到整个action回调跑完才会一次性更新UI,所以你看不到逐帧的动画效果。
正确的实现方式是改用异步任务替代阻塞式的while循环,iOS 15及以上版本可以直接用Swift Concurrency实现,修改后的代码如下:
Button(action: { // 开启异步任务,不阻塞主线程 Task { pass_again = true while(pass_again) { (right_text, pass_again) = twos.collapse(dir: Direction.right) cur_id += 1 // 异步等待1秒,不会阻塞主线程,期间主线程可以正常执行重绘 try? await Task.sleep(nanoseconds: 1_000_000_000) } twos.spawn() } }, label: { Text(right_text) }).padding(0.5)
额外说明:
- 所有用来更新UI的变量(比如
right_text、cur_id这些)需要用@State、@StateObject或者其他能触发SwiftUI视图刷新的属性包装器修饰,只要这些变量的值发生变更,SwiftUI会自动触发重绘,不需要手动调用重绘方法。 - 如果需要适配更低的iOS版本,可以用
Timer来实现定时触发每一步逻辑,替代while循环的写法。
内容的提问来源于stack exchange,提问作者Dyskord
相关产品推荐
相关产品推荐

