SwiftUI 在点击时执行脚本并在视图 window 上 return 输出

SwiftUI execute script on click and return output on view window

我是 SwiftUI 的新手。我对 Python 和 Shell 脚本有中级知识。尝试制作一个基本上 运行 备份作业的应用程序,以将数据从我的 MacOS 复制到网络驱动器。我能够使用 AppleScript 早些时候集成 Python 脚本来实现这一点,但现在我正在尝试用一个有趣的视图实现相同的功能。

使用下面的代码,我正在尝试创建一个函数,该函数可以在从任何位置单击时调用 shell 脚本(更喜欢将脚本存储在应用程序中)(不幸的是,没有看到 Python 在 SwiftUI 中)和 return 视图上的实时输出 window。我正在编写的代码是针对 MacOS 而不是 iPhone 基本上。

谁能帮我指引正确的方向。

import SwiftUI
import Foundation

enum ViewState {
    case DefaultView
    case BackupTaskView
}

struct BackupView : View {
   @State var showing : ViewState = .DefaultView
    
    var body: some View {
        HeaderView()
        VStack {
            if showing == .DefaultView {
                DefaultView(showing:$showing)
            }
            if showing == .BackupTaskView {
                BackupTaskView(showing:$showing)
            }
        }
        .frame(width: 700, height: .infinity, alignment: .topLeading)
        .padding(8)
        
        Spacer()
        FooterView()
    }
}

private struct DefaultView: View {
    
    @Binding var showing : ViewState
    
    @State var navigated = false
    @State var result : String = ""
    
    var body: some View {
        VStack {
            Text(
                "Hello, World!"
            )
        }
        .frame(width: 700, height: .infinity, alignment: .topLeading)
        .padding(8)

        Spacer()

        VStack {
            Button(
                action: { self.showing = .BackupTaskView }
            )
            {
                Image("backup")
                    .resizable()
                    .frame(maxWidth: 180, maxHeight: 180)
            }
            .buttonStyle(PlainButtonStyle())
        }
        
        Spacer()
    }
}

private struct BackupTaskView : View {
    @Binding var showing : ViewState
    @State var result : String = ""
    
    @State var script = "/Users/samiron/Documents/Backup.sh"
    @State var isRunning = false
    
    var body: some View {
        
        VStack {
            Form {
                Section {
                    Text("\(result)")
                }
                .onAppear{self.executeCommand()}
            }
        }
    }
    
    func executeCommand() -> (String?) {
        let task = Process()

        task.launchPath = "/bin/sh"
        task.arguments = [ script ]

        let pipe = Pipe()
        task.standardOutput = pipe
        task.launch()

        let data = pipe.fileHandleForReading.readDataToEndOfFile()
        let result = String(data: data, encoding: .utf8)
        task.waitUntilExit()
        
        return result
    }
}

struct BackupView_Previews: PreviewProvider {
    static var previews: some View {
        BackupView()
    }
}

我假设你想要一些东西,比如

Section {
    Text("\(result)")
}
.onAppear{
  self.result = "Executing..."
  DispatchQueue.global(qos: .background).async {
     let output = self.executeCommand()        // << run in background
     DispatchQueue.main.async {
        self.result = output ?? "Failed"       // << update UI on main
     }
  }
}