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 a test()
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)
}