I have an AppleScript checking if the number of windows of an application is under 1 (there is one or more, or not). If an application has no windows open, the script returns its Bundle ID. So far, everything is fine.
I tried to integrate it into a function in my Swift app, which should return the result of the script as a String. Xcode doesn't tell me any problem, but as soon as my app uses the function, it crashes...
I think the problem is related to the unwrap of the script result, but I'm not sure.
Here's my code:
func checkApp(appBundleID: String) -> String {
let appleScript = """
set bundleID to "\(appBundleID)"
tell application id bundleID
set windowsCount to (count of windows)
end tell
if windowsCount < 1 then
return bundleID
end if
"""
var output = ""
if let script = NSAppleScript(source: appleScript) {
var error: NSDictionary?
output = script.executeAndReturnError(&error).stringValue!
}
return output
}
Your script returns the result of the last AppleScript line, which is a null
AppleEventDescriptor
if the application has one or more windows. This cannot be coerced to string and causes the crash.
My suggestion is to return an optional string in case of an error, for example if the target application is not scriptable, and to return the number of windows coerced to string if there is at least one window.
You could even check error
and return something from the dictionary or create a custom error and return a Result<String,Error>
type
func checkApp(appBundleID: String) -> String? {
let appleScript = """
set bundleID to "\(appBundleID)"
tell application id bundleID
set windowsCount to (count of windows)
end tell
if windowsCount < 1 then
return bundleID
else
return windowsCount as string
end if
"""
var output : String?
if let script = NSAppleScript(source: appleScript) {
var error: NSDictionary?
output = script.executeAndReturnError(&error).stringValue
}
return output
}
Edit: This is a simpler version. It returns the number of windows or -1 if the application is not scriptable.
As the hard-coded script is error-free and the AppleScript error is caught in the script NSAppleScript(source: appleScript)
can be force unwrapped and the error
parameter can be set to nil
.
func checkApp(appBundleID: String) -> Int {
let appleScript = """
set bundleID to "\(appBundleID)"
try
tell application id bundleID
return (count of windows)
end tell
on error
return -1
end try
"""
let script = NSAppleScript(source: appleScript)!
return Int(script.executeAndReturnError(nil).int32Value)
}