How do I run AppleScript Safely inside my Swift app?

Hey there!

I have a Swift app using SwiftUI, and I want to run some AppleScript Safely inside it.

Here is my current code:

func example() {
        var script = NSAppleScript(source: """
        tell application "Music"
            play
            repeat with vlm from 0 to 100 by 1
                set the sound volume to vlm
                delay \(fadetime / 100)
            end repeat
        end tell
        """)
        DispatchQueue.global(qos: .background).async {
            let success = script?.compileAndReturnError(nil)
            assert(success != nil)
            print(success)
        }
    }

However, it does not do anything. I have tried using process, however, that simply errors out in -600 "The application is not running." Is there something I am missing here?

Thank you!

Accepted Reply

Your code calls compileAndReturnError(_:), which only compiles the script. If you want it to run, call executeAndReturnError(_:).

Remember that AppleScript is based on Apple events, so you’ll need permission to send Apple events, meaning:

Finally, don’t use the Dispatch global concurrent queue. See Avoid Dispatch Global Concurrent Queues.


Oh, one last thing. executeAndReturnError(_:) is incorrectly annotated in Objective-C, so Swift things the result is not optional. To get around this, immediately cast the result to an optional. See this post for an example.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Replies

Your code calls compileAndReturnError(_:), which only compiles the script. If you want it to run, call executeAndReturnError(_:).

Remember that AppleScript is based on Apple events, so you’ll need permission to send Apple events, meaning:

Finally, don’t use the Dispatch global concurrent queue. See Avoid Dispatch Global Concurrent Queues.


Oh, one last thing. executeAndReturnError(_:) is incorrectly annotated in Objective-C, so Swift things the result is not optional. To get around this, immediately cast the result to an optional. See this post for an example.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"