Version 15.4 (15F31d) Xcode NSAppleScript of Safari broken

All attempts to script Safari in Xcode using NSAppleScript returns the following message.

error: { NSAppleScriptErrorAppName = Safari; NSAppleScriptErrorBriefMessage = "Application isn\U2019t running."; NSAppleScriptErrorMessage = "Safari got an error: Application isn\U2019t running."; NSAppleScriptErrorNumber = "-600"; NSAppleScriptErrorRange = "NSRange: {32, 3}"; }

Latest script attempt: func getHTML() -> String {

let source = """
tell application "Safari"
  get URL of tab 1 of window 1
end tell

"""

//print(source)
var a = "hello"
var error: NSDictionary?
if let scriptObject = NSAppleScript(source: source) {
    if let scriptResult = scriptObject.executeAndReturnError(&error).stringValue
    {
        a = scriptResult
        print(scriptResult)
    } else if (error != nil)  {
        print("error: ",error!)
    }
}

return a
}

To be clear, you’re not running this in Xcode but using Xcode to build an app that runs this. Right?

If so, there are a number of potential issues. Lemme walk you through a process that works for me:

  1. First run the script in Script Editor to confirm that it works. If it doesn’t work here, you have an AppleScript problem.

  2. Then, in Xcode, create a new project from the macOS > App template.

  3. In Signing & Capabilities, remove App Sandbox. Scripting from a sandboxed app is tricky, so it’s best to start out with the sandbox disabled.

  4. Still in Signing & Capabilities, enable Hardened Runtime > Resource Access > Apple Events. AppleScript is based on Apple events, which the hardened runtime blocks by default.

  5. In the Info tab, add a NSAppleEventsUsageDescription with a privacy string.

    IMPORTANT The property list editor shows this as Privacy - AppleEvents Sending Usage Description.

  6. In ContentView.swift, create a button that calls a test() method.

  7. Add that test() method using the code at the end of this post.

  8. Build and Run the app.

  9. In the app, click the Test button.

  10. The system presents an alert:

    “Test759287“ wants access to control “Safari“. 
    Allowing control will provide access to documents and 
    data in “Safari“, and to perform actions within that app.
    
    [Don’t Allow] [Allow]
    

    Click Allow.

  11. Xcode prints the AppleScript result:

    <NSAppleEventDescriptor: 'utxt'("https://developer.apple.com/forums/thread/759287")>
    

    In this case my frontmost Safari window is, indeed, this DevForums thread (-:

I testing this with Xcode 15.4 on macOS 14.5.

Share and Enjoy

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

func test() {
    let source = """
        tell application "Safari"
            URL of tab 1 of window 1
        end tell
        """
    let script = NSAppleScript(source: source)!
    var errorDict: NSDictionary? = nil
    guard let result = script.executeAndReturnError(&errorDict) as NSAppleEventDescriptor? else {
        print(errorDict!)
        return
    }
    print(result)
}
Version 15.4 (15F31d) Xcode NSAppleScript of Safari broken
 
 
Q