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)
}