We are in the process of sandboxing our app for the Mac App Store. In a non-sandboxed version we rely on launchd plist to automatically restart the app after a crash. How do we retain this ability in a MacApp Store sandboxed version ?
Replies
How do we retain this ability in a MacApp Store sandboxed version ?
There isn’t a direct affordance for this in a sandboxed app, I suspect because it’s a pretty unusal requirement. Why are you trying to do this?
ps You could probably make this work by using a Service Management login item — installed using the SMLoginItemSetEnabled(_:_:) function — to monitor the state of your app and relaunch it if it’s not running. However, I’m not sure what App Review would make of that.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
-
Not sure why the request would be considered unusual. The app is a cloud backup app that monitors folders for changes. If the app crashes the folders are no longer monitored. It is important that the app can be resilient enough to survive a crash, restart and continue monitoring folders. Of course if the end user wants to quit the app it should be able to , but if the app crashes for any reason, like 100 % of app do crash at one point or another, it should have the ability to start again. I am not sure why a sandboxed app would not also have the opportunity to take advantage of toolsets to do this and be against the guides of App Review.
The best solution to this would be one or more XPC Services. Here is Apple documentation on the topic.
The XPC services work like a normal method call, but the method runs in a separate process. If it crashes, you can restart. Technically speaking, your parent app could still crash, but trying to deal with that is a path of greatest resistance.
You might be able to use a helper app too, but that would involve essentially writing your own XPC architecture. I know XPC works in the Mac App Store. A helper app could add some security/privacy complications, especially for an app like you describe. I think XPC is the way to go.
Also, don't forget about alternative ways to accomplish the same thing. You have a cloud backup app. I suppose you want to ensure that it runs on a given schedule. Create a notification to warn the user that the backup hasn't run and schedule it for after the backup should have run. Then, when the backup completes, delete that notification. Repeat forever. Notifications are user-controllable and, therefore, not reliable. But this is still a good fallback idea.
Not sure why the request would be considered unusual.
Because, for historical reasons, the lifetime of the process running your Mac app is visible to the user. For example, it shows up in the Dock, in the app switcher, and so on. As a user it’s distracting to see these things when all you want to do is running a background service.
Most Mac apps that implement a background service do the heavy lifting in a Service Management login item. This login items is either a UI element (LSUIElement) or a background-only app (LSBackgroundOnly), and thus doesn’t show up in the Dock and so on. Use the former if you have limited UI, like a menu bar status item, and the latter if you have no UI.
Service Management login items are an expected feature of Mac App Store apps. Indeed, the SMLoginItemSetEnabled was API was added specifically for that purpose. I don’t work for App Review, and thus can’t make definitive statements on their behalf, but my experience is that the only significant limitation is a UI one, per clause 2.4.5(iii) of the App Store Review Guidelines.
Unfortunately the system doesn’t relaunch a Service Management login item if it crashes. My advice on that front is to put the bulk of the code in another executable and have the Service Management login item launch that, and relaunch it if it crashes. That way your Service Management login item is super simple, and thus unlikely to crash.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"