1

I like to update a text on the screen to inform the user about the progress. I'm using Text in SwiftUI. Whenever I change this message, it should be updated, even if the process is still running. E.g:

@State private var message = "-"

    var body: some View {

        VStack {
            Button("Run") {
                print("Tapped!")
                for i in 0 ... 100 {
                    self.message = "\(i)"
                    for _ in 1...1000 {
                        print(".")  // some time consuming stuff
                    }
                }
            }

            Text(message)
                .frame(width: 100)
                .padding()
        }
        .padding(40)
    }

When I change the message, it should be updating the screen. Unfortunately it only updates the text, when the loops are finished, so it shows 100. It should show 1, 2, ... 100.

Do I need special tricky queues like in the classic development using "DispatchQueue.main.async" etc or is there an easier way in SwiftUI?

Peter71
  • 2,180
  • 4
  • 20
  • 33

2 Answers2

1

swift is too fast for just printing out 1000 statements...

by the way...the time consuming stuff should be done always NOT on the main thread and the UI Stuff should always be done on the main thread ;)

try this

struct ContentView: View {
    @State private var message = "-"

    var body: some View {

        VStack {
            Button("Run") {
                print("Tapped!")
                OperationQueue().addOperation {
                    for i in 0 ... 100 {

                        OperationQueue.main.addOperation {
                            self.message = "\(i)"
                        }
                        sleep(1)
                    }

                }
            }

            Text(message)
                .frame(width: 100)
                .padding()
        }
        .padding(40)
    }
}
Chris
  • 7,579
  • 3
  • 18
  • 38
1

I prefer DispatchQueue, so some alternate

Button("Run") {
    print("Tapped!")
    DispatchQueue.global(qos: .background).async {
        for i in 0 ... 100 {
            DispatchQueue.main.asych {
                self.message = "\(i)"
            }
            for _ in 1...1000 {
                print(".")  // some time consuming stuff
            }
        }
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690