swift - 如何创建具有延迟的 for 循环以每 X 秒显示一条消息?
问题描述
我正在尝试创建一个获取数组内容并显示每个元素(文本)的函数,我正在使用 swiftUI @State 变量来存储消息,我还尝试了环境对象变量来存储消息并显示它们一个文本(“”)。目前该函数只显示数组中的最后一条消息,它只存储数组中的结束循环元素。
请让我知道如何一次延迟显示每条消息
谢谢
@State var messages = ["Welcome","FirstName","LastName"]
@State var message = ""
func DisplayMessageAnimation(messages: [String]) {
for i in 0..<messages.count {
// your code here
self.message = messages[i]
print(" message", self.message)
sleep(UInt32(5.0))
}
}
解决方案
您应该使用重复计时器,如果视图消失,您可以取消该计时器。
例如旋转字符串:
import Combine
struct ContentView: View {
@State var message = "Hello, world!"
@State var timer: AnyCancellable?
var body: some View {
VStack {
Text(message)
Button(action: {
self.startRepeatingRotation(with: ["foo", "bar", "baz"])
}) {
Text("Start rotating messages")
}
}.onDisappear {
self.timer?.cancel()
}
}
private func startRepeatingRotation(with messages: [String]) {
guard !messages.isEmpty else { return }
var index = 0
self.message = messages[0]
self.timer = Timer.publish(every: 5, on: .main, in: .common).autoconnect().sink { output in
index = (index + 1) % messages.count
self.message = messages[index]
}
}
}
或者,如果您希望它在序列结束时停止,即非重复序列,也许:
private func startRotation(with messages: [String]) {
guard !messages.isEmpty else { return }
var index = 0
self.message = messages[0]
self.timer = Timer.publish(every: 5, on: .main, in: .common).autoconnect().sink { output in
index += 1
guard index < messages.count else {
self.timer?.cancel()
return
}
self.message = messages[index]
}
}
FWIW,
从不睡觉”。你永远不想阻塞主线程。
你也不应该使用
asyncAfter
。如果你这样做了,即使你关闭了有问题的视图,那些预定的调度也会留在外面,等待运行。如果未来的时间间隔很远,您将开始看到这些单独asyncAfter
调用的“合并”,而不是像您希望的那样每五秒运行一次。
推荐阅读
- html - Google Apps脚本如何将事件侦听器添加到一组具有相同名称的复选框中的每个复选框
- c++ - 具有交错类型和非类型参数的参数包的模板
- vue.js - vuex 模块 appState 不适用于作为第一个参数传递的模块命名空间
- c# - 如何在asp.net MVC 5中以引导模式显示各种内容?
- assembly - 在 68k 中实现 while 循环
- php - 打开购物车 | 为所有客户组设置默认税率,包括将来可能添加的客户组 | PHP
- c - 需要帮助找到解决问题的逻辑解决方案
- python - 利用 Tkinter 的 Grid Manager 将按钮居中并填充整个框架
- oracle - 使用 kafka 从 oracle 流式传输数据
- nlp - 如何在 BILOU 的其他模型中使用地名词典特征作为输入