在 SwiftUI 中实现 延迟操作,推荐使用 Task.sleep,因为它是非阻塞的异步方法,适合现代 Swift 的并发环境。
Task.sleep 用法
Task.sleep 用于延迟异步操作,接受参数为纳秒(nanoseconds)。以下是常见用法:
Task {
try? await Task.sleep(nanoseconds: 20_000_000_000) // 延迟 20 秒
endOfWait = true
}
基本示例
import SwiftUI
struct ContentView: View {
@State private var isLoading = false
var body: some View {
VStack {
if isLoading {
ProgressView("Loading...")
} else {
Text("Task Completed!")
}
Button("Start Task") {
Task {
isLoading = true
try? await Task.sleep(nanoseconds: 2_000_000_000) // 延迟 2 秒
isLoading = false
}
}
}
.padding()
}
}
说明:
Task.sleep(nanoseconds:) 接收延迟时间(单位为纳秒)。
1 秒 = 1_000_000_000 纳秒
2 秒 = 2_000_000_000 纳秒
不会阻塞主线程,适合在 SwiftUI 环境下使用。
在 onAppear 中使用延迟
struct ContentView: View {
@State private var message = "Waiting..."
var body: some View {
Text(message)
.onAppear {
Task {
try? await Task.sleep(nanoseconds: 3_000_000_000) // 延迟 3 秒
message = "Done!"
}
}
.padding()
}
}
当视图首次显示时,会延迟更新状态。
模拟加载数据
用于模拟网络请求或长时间任务:
struct ContentView: View {
@State private var isLoading = false
@State private var data: String?
var body: some View {
VStack {
if isLoading {
ProgressView("Loading data...")
} else if let data = data {
Text("Loaded Data: \(data)")
} else {
Text("No data yet")
}
Button("Fetch Data") {
Task {
isLoading = true
try? await Task.sleep(nanoseconds: 2_000_000_000) // 模拟 2 秒网络延迟
data = "Sample data from server"
isLoading = false
}
}
}
.padding()
}
}
注意事项
1、不要阻塞主线程
避免使用以下代码,因为它会阻塞主线程,导致 UI 停滞:
Thread.sleep(forTimeInterval: 2.0) // 阻塞主线程,不推荐!
相反,应使用异步 Task.sleep:
try? await Task.sleep(nanoseconds: 2_000_000_000) // 推荐
2、异步上下文要求
Task.sleep 必须在异步上下文中使用,因此应在 Task 或 async 函数中调用:
func performTask() async {
try? await Task.sleep(nanoseconds: 1_000_000_000)
print("Task completed")
}
调用方式:
Task {
await performTask()
}
总结
使用 Task.sleep 实现非阻塞延迟。
配合 SwiftUI 的异步环境更新视图状态。
应避免阻塞主线程的方式(如 Thread.sleep)。
对于复杂的延迟任务,可以结合 async/await 和 Task 来实现更加高效的异步操作。