Home > database >  How to create a button which runs a bash script in SwiftUI
How to create a button which runs a bash script in SwiftUI

Time:10-23

I'm not a swiftui programmer at all but trying to create a really simple application that runs a .sh script for me, have tried googling endlessly but can't seem to get it to work. I've also tried running commands from the terminal in swift (since the .sh script just cds into a location and runs a jar).

 import SwiftUI

    struct ContentView: View {
        @State var isRunning = false
        
        var body: some View {
            VStack {
                HStack {
                    Button(action: {
                        let executableURL = URL(fileURLWithPath:"/Users/myname/Desktop/run.sh")
                        self.isRunning = true
                        try! Process.run(executableURL,
                                         arguments: [],
                                         terminationHandler: { _ in self.isRunning = false })
                    }) {
                        Text("Run")
                    }.disabled(isRunning)
                        .padding(.trailing)
                }
            }.frame(maxWidth: .infinity, maxHeight: .infinity)
        }
    }


    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }

I have also ran chmod x run.sh on the file aswell as disabling sandboxing on the target/app itself

It builds fine, but when the button is pressed you get an error in xCode

Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=NSCocoaErrorDomain Code=4 "The file “run.sh” doesn’t exist." UserInfo={NSFilePath=/Users/myname/Desktop/run.sh}

Even though I am 100% positive that I have that file on the desktop, with the correct extension.

Any ideas?

CodePudding user response:

It is impossible to access the Desktop path unless the user explicitly chooses to do it, due to sandbox restrictions of Apple, which can be found under Signing & Capabilities but what you could do is you can force the user to choose the script file they want to run or you can place your script to one of the folders defined on File Access section

image

with a code like this:

if let path = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first { // or .documentsDirectory 
    // also use .downloadsDirectory if and only if you allowed `Downloads Folder` on `Signing & Capabilities`
    
    let executableURL = path.appendingPathComponent("new.sh")
    self.isRunning = true
    try! Process.run(executableURL,
                     arguments: [],
                     terminationHandler: { _ in self.isRunning = false })
}

and also you can just use documentsDirectory like all other apps do. Believe it or not, it is really good for Apple to do this kind of restrictions because it would be horrible if all the apps would have access to the desktop directory, write/delete and edit all the stuff and dirten the beautiful scene of the desktop, not mentioning the security issues also.

  • Related