Изменение текстового вида - отображение прогресса длительной операции

Я пытаюсь показать ход длительной операции в текстовом представлении. Используя StateObject/Published var, я надеялся увидеть изменение текста при изменении опубликованного var, однако я вижу только последний текст, появляющийся в текстовом поле. Как я могу динамически изменять/обновлять текстовое поле?

          @StateObject var tt = TestText()
    
    var body: some View {
        Text(tt.text)
            .padding()
            .onAppear(perform: { tt.ChangeText() })
    }
      class TestText: ObservableObject {
    
    @Published var text = "text 0"
    
    func ChangeText() -> Void {
        sleep(3)         // some time-consuming stuff here
        text = "text 1"
        sleep(3)         // id
        text = "text 2"
        sleep(3)         // id
        text = "text 3"
        sleep(3)         // id
        text = "text 4"
        sleep(3)         // id
        text = "text 5"
    }
}

2 ответа

твойsleep(3)неправильно, он не имитирует длительную задачу,
он останавливает все (включая обновление пользовательского интерфейса) на 3 секунды. То, что вы хотите, это что-то вроде этого, чтобы имитировать длительную задачу:

       struct ContentView: View {
    @StateObject var tt = TestText()
    
    var body: some View {
        Text(tt.text)
            .padding()
            .onAppear(perform: { tt.ChangeText() })
    }
}

 class TestText: ObservableObject {
     @Published var text = "text 0"
     
     func ChangeText() -> Void {
         DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
             self.text = "text 1"
         }
         DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
             self.text = "text 2"
         }
         DispatchQueue.main.asyncAfter(deadline: .now() + 6) {
             self.text = "text 3"
         }
         DispatchQueue.main.asyncAfter(deadline: .now() + 8) {
             self.text = "text 4"
         }
         DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
             self.text = "text 5"
         }
     }
 }

Спасибо, что указали мне правильное направление. Сон был просто заполнителем для длительной операции, но различные операции выполняются последовательно. С небольшой модификацией вашего кода я достиг своей намеченной цели. Теперь биты кода запускаются один за другим, показывая обновленный текст после каждого шага.

      import Foundation

class TestText: ObservableObject {
    
    @Published var text = "text 0"
    
    func ChangeText() -> Void {
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            self.DoSomething()
            self.text = "text 1"
            
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                self.DoSomething()
                self.text = "text 2"
                
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                    self.DoSomething()
                    self.text = "text 3"
                    
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                        self.DoSomething()
                        self.text = "text 4"
                        
                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                            self.DoSomething()
                            self.text = "text 5"
                        }
                    }
                }
            }
        }
    }
    
    func DoSomething() -> Void {
        sleep(3)  // these are in fact various bits of codes, which have to run in sequence one after the other, DoSomething is just a placeholder for the moment
    }
}
Другие вопросы по тегам