Avoiding bundle self-modification

Apple recommends to stop bundle self-modification as soon as possible:


"If you used custom resource rules because your program modifies itself

as it is running, you should stop doing this as soon as possible. If you

transport such a modified app to another computer by web download,

email, AirDrop, etc., the modified copy at the receiving end will be

quarantined. This will trigger the Gatekeeper check the first time the

app is run on the receiving machine, and the app will not be allowed to

run because of the broken signature."


https://developer.apple.com/library/archive/technotes/tn2206/_index.html#//apple_ref/doc/uid/DTS40007919-CH1-TNTAG401


Q1: My question is about the standard practice of saving the data outside the bundle. Namely, how to handle program removal. When the data is saved inside the bundle, removing the bundle means also removing the data. But when data is saved into ~/Library/Application Support, it means we need some kind of uninstaller and instead of a single bundle we have a directory containing both the bundle and its uninstaller. When installed in /Applications this directory is displayed as two applications in Launchpad: the main bundle and the uninstaller, which doesn't look nice to me. Or is it ok? What's the standard way to handle situations like this one? Perhaps it's somehow possible to make macOS silently call the uninstaller when the user removes the main bundle from the Launchpad?


Q2: I've also read somewhere (cannot find the link atm) that with the upcoming macOS Catalina the bundle signatures will be periodically checked by the OS, so self-modifying bundles may have issues running even without being sent over the internet. Is it true?


Thanks


PS. This question was originally posted in the wrong place here:
https://discussions.apple.com/thread/250557758


UPD: As I understand the standard way for Q1 is to use App Store installation. In that case there's a little ✖ near the application icon in Launchpad when Option is pressed and the uninstallation is handled by the OS. For other installers downloaded from the internet there's little that could be done to handle uninstallation automatically by the OS. Am I correct?

Replies

I think you are worrying too much about it. You are correct that you would need some kind of uninstaller to remove ancillary data. But even if you went to the trouble of making one, most people wouldn't use it. I have seen some apps monitor their app bundle and prompt the user to complete the uninstall when they detect that the app has been moved to the trash. I'm not sure if that could be done in an Mac App Store context. It would have to be implemented with a login item and I'm not sure if the login item would stay running long enough to finish the uninstall if the app was deleted.


Also, one of the primary reasons that people will uninstall an app is due to some real or preceived bug in the software. They don't realize that is ineffective. But they would be most upset if all their data was automatically removed.


If you really, really want to support this, the best way to do it would be to incorporate an uninstaller inside the app. I'm pretty sure that if you set LSUIElement to true in the info.plist file then it won't show up in launchpad. Most people won't use it. But then, most people won't notice that there is a bunch of data sitting in a hidden folder either. If they complain, you can tell them to reinstall the app and use the appropriate uninstaller. This applies to Mac App Store apps too. The app data is just in a different folder. In the Mac App Store case, you might want to rename the option to be "reset data" or something.

I’m with john daniel on this one. In general, it’s better not to sweat the details here.

There are a couple of edge cases that warrant further exploration:

  • Your app’s data is huge, downloaded video files, for example — One option here is to store this data in the Caches directory, so that the OS can clean up if it runs short on disk space.

  • Your app’s data is sensitive, such that user won’t want to leave it lying around on disk — In that case I think a UI command to clear that data is your best option.

WARNING Storing data within your app’s bundle is problematic. That approach has been causing problems for users for decades (even back on the Mac 128, folks wanted to be able to run apps from a locked floppy). Doing it on current system will break the app’s code signature, and that’s likely to cause more problems in the future. You really need to change your approach.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you guys for your advice. I had a short discussion with a colleague. The main argument against the uninstaller is, as john daniel correctly pointed out, that users indeed sometimes reinstall applications in an attempt to solve their issues with the software, losing their data on reinstallation would be unpleasant surprise. The data is not sensitive to potential theft but consumes a bit of space. It should persist as long as the app is not uninstalled, so I guess ~/Library/Application Support is the right location.