Как создать для l oop с задержкой отображение сообщения каждые Х секунд? - PullRequest
1 голос
/ 25 марта 2020

Я пытаюсь создать функцию, которая принимает содержимое массива и отображает каждый элемент (текст), я использую переменную swiftUI @State для хранения сообщения, я также пробовала переменные объекта среды для хранения сообщений и отобразить их в тексте (""). В настоящее время функция Отображает только последнее сообщение в массиве, в массиве хранится только конечный элемент l oop.

Пожалуйста, дайте мне знать, как я могу отображать каждое сообщение с задержкой за раз

Спасибо

@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))
    }  
}

Ответы [ 3 ]

0 голосов
/ 25 марта 2020

Использовать asyncAfter в основном потоке. Запланируйте все казни через желаемые интервалы и позвольте им произойти, например:

for i in 0..<messages.count {

    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(5 * i)) {
        self.message = messages[i]
        print("\(self.message) message", self.message)
    }
}
0 голосов
/ 25 марта 2020

Вы должны использовать повторяющийся таймер, который можно отменить, если вид исчезает.

Например, чтобы вращаться через строки:

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, а не выполнение их каждые пять секунд, как вы хотели.

0 голосов
/ 25 марта 2020

Я думаю, что это так

for i in items {
do {
    sleep(4)
   }
   // Your code here
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...