I am developing a background application that acts as a metadata server under MacOS written in Swift. Sandboxed clients prompt the user to select URLs which are passed to the server as security scoped bookmarks via an App Group and the metadata will be passed back. I don't want the I/O overhead of passing the complete image file data to the server. All the variations I have tried of creating security scoped bookmarks in the client and reading them from the server fail with error messages such as "The file couldn’t be opened because it isn’t in the correct format." Can anyone guide me in the right direction or is this just not possible?
OK. A login item that you install this way runs for the duration of the user’s login session. That’s a key design point, because it opens up other options.
My advice here is that you:
-
Use
SMAppService
to install alaunchd
agent. -
Have that agent publish a named XPC endpoint.
-
Have client apps open the file they want to process.
-
And then send the file descriptor to the agent using XPC.
This has a bunch of nice attributes:
-
In contrast to login items,
launchd
agents run on demand. That means that your background process will only run when there are active clients [1]. -
The fact that, in step 3, the client opens the file means that there’s no messing around with permissions. Clients can process any file that they can open.
This design assumes that you have multiple different client apps. If the client is always the app that contains the agent, you might want to look at an XPC service instead.
One thing to watch out for here is access control. For a client to connect to the agent’s named XPC endpoint:
-
It must share an app group with the agent, which in turn means it must be published by the same team.
-
Or it must not be sandboxed.
-
Or it must use a temporary exception entitlement to allow this access [2]. Such entitlements are fine in general but will cause complications if you try to publish the client on the App Store.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] In reality, macOS only terminates idle agents when the system is under memory pressure, so you won’t see it immediately terminate as soon as the last client goes away.
[2] For more on that, see the links in App Sandbox Resources.