Hello,
I'm trying to make a white-Label sort of thing for my app, that is: a script runs before the app launches, sets a certain LaunchAgent command that sets and environment variable, and based on that variable's value tha main app's icon changes to a certain logo (change only happens in the dock because changing the icon on disk breaks the signature)
When the app launches it takes a noticeable time until the dock icon changes to what I want, so I worked around that by setting the app's plist property to hide the dock icon and then when the app is launched I call an objc++ function to display the icon in the dock again (this time it displays as the new icon)
The showing happens through [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
The problem happens when I try to close the app, it returns back to the old logo before closing which is what I want to prevent. I tried hiding the app dock icon before closing but even the hiding itself changes the icon before hiding
The hiding happens through [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];
My goal is that the main app icon doesn't appear to the user through the dock, and that the icon that is only visible is the other one that changes during runtime
The reason for this is that I have an app that should be visible differently depending on an environment variable that I set using an installer app. The app is the same for all users with very minor UI adjustments depending on that env variable's value. So instead of creating different versions of the app I'd like to have just 1 version that adjusts differently depending on the env variable's value. Somehow this is the only step left to have a smooth experience
Feel free to ask more clarification questions I'd be happy to help Thank you
It’s better to reply as a reply, rather than in the comments; see Quinn’s Top Ten DevForums Tips for this and other titbits.
Thanks for those answers.
My advice here is that you change tack. Rather than try to set this at runtime based on an environment variable, have your installer install an app with the right icon.
That doesn’t mean that you need N installers for your N icons. There are a couple of ways that you can customise the icon on the fly.
The first is to have a post-install script that applies a custom icon to your app. This has one key advantage: It’s easy to implement (-: Specifically, setting a custom icon doesn’t affect the app’s code signature.
However, I’m not sure it’s actually the right option for you, because of the issues you raised in your other thread, Changing the menu bar display name. There’s no way to set a custom app name like this.
Honestly, I can’t think of a good way to set the app name at all. macOS expects apps to be static artefacts. While you can change some of this stuff at runtime — like the icon, for example — that’s the exception rather than the rule.
To get this level of customisation you need to ship multiple apps. However, that doesn’t mean you need to ship multiple installers. You can have a single installer that holds all the apps, deduplicating stuff to minimise the package size, and then install the right one based on the user’s choice.
However, this is no longer easy. There are two tricky issues:
- The app’s
Info.plistis sealed over by its code signature, so you can’t change values there without re-signing the app. - You want each app to have its own unique main executable UUID, as explained in TN3178: Checking for and resolving build UUID problems.
The solution is:
- Build, sign, and notarise the app N times.
- Use one of the app’s as the base for your installer.
- For the remaining N - 1 apps, diff it against that app and store the diffs.
- Have your installer install the base app and then the appropriate diff.
The diffs should be quite small, being limited to:
- The
Info.plist - The icon [1]
- The main executable [2]
- Some files in
Contents/_CodeSignaturethat hold various bits of code signature
The end result of this is that the installed app has a valid code signature, a unique main executable UUID, and a custom app name and icon, which should be sufficient to avoid all the weird edge cases you’re seeing.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] Another option is to include all the icons in the base app and then just change the Info.plist value that references the icon. This should result in a smaller diff.
[1] If the main executable is large, you can reduce it by moving the bulk of your app’s code to a framework (or dynamic library) nested in the app’s bundle and then have the main executable be a stub that just calls through to that framework.