I'm building an application for macOS and for some of it's functionality I rely on calling AppleScript:
let appleScript = NSAppleScript(source: theScriptIWantToExecute)
var errorDict: NSDictionary? = nil
let possibleResult = appleScript?.executeAndReturnError(&errorDict)
Now I've discovered that some scripts in some circumstances on some applications when they fail they rather than throw an error they crash the whole application. While it's bad that the script fails it's not so critical that the whole UI should crash.
My idea was to separate out the "Apple Script Execution" part into a completely separate process that will be called by the main application. In case it crashes, it can simply be restarted without any consequence for the main app.
I've been thinking what would be the best solution. Since it's more or less a functional problem I've been tempted to use a command line tool, but command line tools only return text if I'm not mistaken. I would rather return some objects. But I don't really need a service.
XPC seems to support this but is geared more towards services.
What is the best way to isolate my main app from these crashes while still being able to use high level objects?
For those interested in how I fixed it:
- Create a separate XPC project (the template code is pretty fine to start off with)
- Create a separate project with all of the types you want to share "across the bridge" and import it in both targets
If you don't share the types you're going to have a lot of confusing build- and run-time problems.
CodePudding user response:
You can do this using an XPC service. In fact "stability" is one of the two key reasons Apple created XPC services. So if this instability is unavoidable, then creating an XPC service is a good way to go about doing this.
Apple provides two main ways to communicate with an XPC service: their XPC C framework and their
Objective-C framework which is often referred to as the
NSXPCConnection
API. While both can be used from Swift with its built in language bridging functionality, neither are particularly pleasant to use from Swift. I've created SecureXPC which is written from the ground up for Swift and I think is quite a bit easier and nicer to use.