Home > Enterprise >  SwiftUI async redirect output on view like console output (Realtime)
SwiftUI async redirect output on view like console output (Realtime)

Time:01-04

I am a SwiftUI learner. Trying to run a simple function on MacOS, that stdout on view just like console. With below code it prints output on view once the execution gets finished. Is there anyway that I can redirect output to view realtime? Please help me. Thanks in advance!

struct MainView : View {
    @State var Log : String = ""
    var body: some View {
        VStack {
            Form {
                Section {
                    Text("\(Log)")
                }
                .onAppear {
                    DispatchQueue.global(qos: .background).async {
                       Task {
                            let output = await self.runCodeAsync()
                            DispatchQueue.main.async {
                                Log.append(output)
                            }
                        }
                    }
                }
            }
        }
    }

    func runCodeAsync() async -> (String) {
        
        let task = Process()
        task.executableURL = URL(fileURLWithPath: "/sbin/ping")
        task.arguments = [ "-c", "3", "127.0.0.1" ]

        let outputPipe = Pipe()
        task.standardOutput = outputPipe
        await task.launch()    //Xcode Warning: no 'async' operations occur within 'await' expression

        let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
        let output = String(decoding: outputData, as: UTF8.self)

        return await output    //Xcode Warning: no 'async' operations occur within 'await' expression
    }
}

CodePudding user response:

try the following code, without using async:

EDIT-1:

struct MainView: View {
    @State var log: String = "testing"
    
    var body: some View {
        Text(log)
            .onAppear {
               runCode()
            }
            .frame(width: 444, height: 444)
    }
    
    func runCode() {
        let task = Process()
        task.executableURL = URL(fileURLWithPath: "/sbin/ping")
        task.arguments = [ "-c", "3", "127.0.0.1" ]
        let outputPipe = Pipe()
        task.standardOutput = outputPipe
        let outputHandle = outputPipe.fileHandleForReading
        outputHandle.readabilityHandler = { pipe in
            if let ouput = String(data: pipe.availableData, encoding: .utf8) {
                if !ouput.isEmpty {
                    log  = " "   ouput
                    print("----> ouput: \(ouput)")
                }
            } else {
                print("Error decoding data: \(pipe.availableData)")
            }
        }
        task.launch()
    }
}
  •  Tags:  
  • Related