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:
-
First run the script in Script Editor to confirm that it works. If it doesn’t work here, you have an AppleScript problem.
-
Then, in Xcode, create a new project from the macOS > App template.
-
In Signing & Capabilities, remove App Sandbox. Scripting from a sandboxed app is tricky, so it’s best to start out with the sandbox disabled.
-
Still in Signing & Capabilities, enable Hardened Runtime > Resource Access > Apple Events. AppleScript is based on Apple events, which the hardened runtime blocks by default.
-
In the Info tab, add a
NSAppleEventsUsageDescription
with a privacy string.IMPORTANT The property list editor shows this as Privacy - AppleEvents Sending Usage Description.
-
In
ContentView.swift
, create a button that calls atest()
method. -
Add that
test()
method using the code at the end of this post. -
Build and Run the app.
-
In the app, click the Test button.
-
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.
-
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) }