SwiftUI 在单击时执行脚本并在视图窗口上返回输出

Posted

技术标签:

【中文标题】SwiftUI 在单击时执行脚本并在视图窗口上返回输出【英文标题】:SwiftUI execute script on click and return output on view window 【发布时间】:2022-01-19 05:51:06 【问题描述】:

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

使用下面的代码,我正在尝试创建一个函数,该函数可以从任何位置(不幸的是在 SwiftUI 中没有看到 Python 的任何本机解决方案)单击时调用 shell 脚本(最好将脚本存储在应用程序中)并返回实时输出在视图窗口上。我正在编写的代码基本上是针对 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)")
                
                .onAppearself.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()
    

【问题讨论】:

【参考方案1】:

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

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
     
  

【讨论】:

以上是关于SwiftUI 在单击时执行脚本并在视图窗口上返回输出的主要内容,如果未能解决你的问题,请参考以下文章

为啥单击 SwiftUI 中的列表项后列表视图项变为灰色?

单击按钮时剑道网格不会打开剑道窗口

从目标视图返回时,SwiftUI NavigationLink 显示为突出显示

SwiftUI 在按钮上触发操作而无需用户单击按钮

SwiftUI - 在按钮单击时添加一行多个文本字段/视图

SwiftUI 视图首选项:overlayPreferenceValue 在复杂容器上使用时返回 nil