microsoft / microsoft/react-native-test-app
iOS: add support for alternate app icons
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 674
- Forks
- 97
- Avg merge
- 21h 43m
- Merged PRs (30d)
- 20
Description
Proposal
In iOS, people can choose an alternate app icon: https://developer.apple.com/design/human-interface-guidelines/foundations/app-icons
Technically, the option is also available to macOS, but it doesn't seem like it's supported according to docs. For now, supported platforms include iOS, iPadOS, and visionOS.
Alternatives
n/a
Implementation Details
#1022 put down a lot of the foundation already. We need to add a few more props to Info.plist, such as CFBundleAlternateIcons, when alternateIcons is set.
Configuration
Alternate icons are configured under icons.alternateIcons:
{
"ios": {
"icons": {
"primaryIcon": {
"filename": "AppIcon.png",
"prerendered": true
},
"alternateIcons": {
"AppIconBlue": {
"filename": "AppIconBlue.png",
"prerendered": false
},
"AppIconRed": {
"filename": "AppIconRed.png",
"prerendered": true
}
}
}
}
}
Each property name under alternateIcons:
- Is the alternate icon's unique identifier.
- Is used as the asset-catalog name.
- Is passed to APIs such as
UIApplication.setAlternateIconName(...). - Must be a valid, non-reserved asset-catalog identifier.
Implementation Details
When alternateIcons contains valid entries:
- Generate an
.appiconsetfor each alternate icon (similar to #1022). - Add each alternate icon under
CFBundleIcons.CFBundleAlternateIconsin the generatedInfo.plist. - Use the same icon-entry format as
CFBundlePrimaryIcon, including:CFBundleIconNameCFBundleIconFilesUIPrerenderedIcon
- Set
UIPrerenderedIconfrom the manifest entry's prerendered value. - Configure
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMESwith the names of all valid alternate icon sets.
For the example above, the generated plist should contain entries equivalent to:
<key>CFBundleIcons</key>
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>AppIconBlue</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<!-- Generated icon files -->
</array>
<key>CFBundleIconName</key>
<string>AppIconBlue</string>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>AppIconRed</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<!-- Generated icon files -->
</array>
<key>CFBundleIconName</key>
<string>AppIconRed</string>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
</dict>
</dict>
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES should contain:
AppIconBlue AppIconRed
The exact serialization may differ as long as the generated plist and build setting are semantically equivalent.
Invalid Entries
Invalid or reserved identifiers must not fail project generation.
For each invalid entry:
- Emit a warning identifying the ignored icon and the reason it is invalid.
- Do not generate its asset catalog.
- Do not add it to
CFBundleAlternateIcons. - Do not add it to
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES. AppIcon, which is reserved for the primary icon, must be treated as invalid when used as an alternate icon identifier.
Warnings should not prevent other valid alternate icons from being processed.
Additional Context
No response
Code of Conduct
- I agree to follow this project's Code of Conduct
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read the icon-generation foundation from #1022 first, then trace where iOS asset catalogs, Info.plist entries, and build settings are generated. Done means valid alternate icons produce their asset catalogs, plist metadata, and compiler names, while invalid or reserved identifiers are skipped with warnings without blocking valid entries.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ios, react-native, typescript
- Domain
- build-system, mobile
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100