Search code examples
swifttextviewproperty-wrapper-published

Changing text view - showing progress lengthy operation


I'm trying to show progress of a lengthy operation in a Text view. Using StateObject/Published var, I was hoping to see the Text change when the published var changes, however, I only see the last text appearing in the Text field. How can I dynamically change/update the Text field?

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

Solution

  • Thanks for pointing me in the right direction. The sleep was just a placeholder for a lengthy operation, but the various operations run sequentially. With some slight modification to your code I achieve my intended goal. Now the code-bits run one after the other, showing the updated text after each step.

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