SwiftUI中True delay延迟动画原生实现方案及代码优化咨询
现有代码优化建议
- 使用
usleep阻塞后台线程的实现资源消耗较高,且GCD异步任务未绑定视图生命周期,若视图提前销毁仍会执行主线程更新操作,存在冗余资源占用风险 - 手动切换全局队列和主队列的写法冗余,不符合当前SwiftUI的最佳实践规范
原生实现方案
推荐两种官方原生的实现方式,无需自定义线程调度逻辑,和你现有效果一致:
方案1:Swift Concurrency 动态逐个添加元素(适配元素数量动态变化场景)
使用Task配合系统内置的sleep方法实现,自动绑定视图生命周期,视图销毁时任务会自动取消,无需手动管理线程:
struct ContentView: View { @State private var array: [Int] = [Int]() var body: some View { VStack(spacing: 10.0) { Button("remove all") { array.removeAll() }.foregroundColor(.red) Button("Way 1") { array += Array(repeating: 0, count: 5) } Button("原生延迟动画实现") { Task { for index in 0...5 { // 50毫秒延迟,等价于原有usleep(50_000) try await Task.sleep(nanoseconds: 50_000_000) array.append(index) } } } ForEach(array.indices, id:\.self) { index in Image(systemName: "arrowtriangle.up.fill") .scaledToFit() .frame(width: 25, height: 25) } } .animation(.default, value: array) } }
方案2:一次性加载+按索引延迟动画(适配元素数量固定场景,性能更优)
如果元素总量固定,可以一次性完成元素布局,仅通过动画延迟实现逐个出现效果,渲染效率更高:
struct ContentView: View { @State private var showAll = false private let totalCount = 6 var body: some View { VStack(spacing: 10.0) { Button("remove all") { showAll = false }.foregroundColor(.red) Button("原生高性能延迟动画") { showAll = true } ForEach(0..<totalCount, id:\.self) { index in if showAll { Image(systemName: "arrowtriangle.up.fill") .scaledToFit() .frame(width: 25, height: 25) .animation(.default.delay(Double(index) * 0.05), value: showAll) } } } } }
效果演示:
内容的提问来源于stack exchange,提问作者swiftPunk
相关产品推荐
相关产品推荐

