首页 > 解决方案 > 如何创建具有延迟的 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))
    }  
}

标签: swiftswiftui

解决方案


您应该使用重复计时器,如果视图消失,您可以取消该计时器。

例如旋转字符串:

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调用的“合并”,而不是像您希望的那样每五秒运行一次。


推荐阅读