diff --git a/Sources/Bedrock/Branding/BRANDING_GUIDE.md b/Sources/Bedrock/Branding/BRANDING_GUIDE.md
index 335dfcb..361f1f1 100644
--- a/Sources/Bedrock/Branding/BRANDING_GUIDE.md
+++ b/Sources/Bedrock/Branding/BRANDING_GUIDE.md
@@ -139,8 +139,14 @@ import Bedrock
struct YourApp: App {
var body: some Scene {
WindowGroup {
- AppLaunchView(config: .yourApp) {
- ContentView()
+ ZStack {
+ // Base background matching launch screen - prevents flash
+ Color.Branding.primary
+ .ignoresSafeArea()
+
+ AppLaunchView(config: .yourApp) {
+ ContentView()
+ }
}
}
}
@@ -152,6 +158,9 @@ struct YourApp: App {
- Fades smoothly into your main content
- Creates a polished, professional app opening experience
+**Why the ZStack?**
+The `AppLaunchView` renders your main content underneath the launch overlay from the start. Without the base `Color.Branding.primary` layer, the main content's background (often white) can flash briefly before the launch screen covers it. The ZStack ensures the entire window is filled with your brand color from the first frame.
+
---
## Step 3: Set Launch Screen Background Color
@@ -167,6 +176,8 @@ YourApp/Resources/Assets.xcassets/LaunchBackground.colorset/Contents.json
With this content (update RGB values to match your `Color.Branding.primary`):
+**Important:** Include both light and dark mode variants with identical colors to prevent issues when the device is in dark mode.
+
```json
{
"colors" : [
@@ -175,9 +186,27 @@ With this content (update RGB values to match your `Color.Branding.primary`):
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
- "blue" : "0.800",
- "green" : "0.500",
- "red" : "0.300"
+ "blue" : "0.220",
+ "green" : "0.120",
+ "red" : "0.050"
+ }
+ },
+ "idiom" : "universal"
+ },
+ {
+ "appearances" : [
+ {
+ "appearance" : "luminosity",
+ "value" : "dark"
+ }
+ ],
+ "color" : {
+ "color-space" : "srgb",
+ "components" : {
+ "alpha" : "1.000",
+ "blue" : "0.220",
+ "green" : "0.120",
+ "red" : "0.050"
}
},
"idiom" : "universal"
@@ -190,7 +219,21 @@ With this content (update RGB values to match your `Color.Branding.primary`):
}
```
-### 3.2 Update Xcode Project Settings
+### 3.2 Add UILaunchScreen to Info.plist
+
+Add this dictionary to your app's `Info.plist`:
+
+```xml
+UILaunchScreen
+
+ UIColorName
+ LaunchBackground
+
+```
+
+This explicitly tells iOS to use your color asset for the system launch screen background.
+
+### 3.3 Update Xcode Project Settings
In your `project.pbxproj`, add this line after `INFOPLIST_KEY_UILaunchScreen_Generation = YES;` in **both** Debug and Release build configurations:
@@ -422,8 +465,14 @@ import Bedrock
struct MyCameraApp: App {
var body: some Scene {
WindowGroup {
- AppLaunchView(config: .myCamera) {
- ContentView()
+ ZStack {
+ // Base background matching launch screen - prevents flash
+ Color.Branding.primary
+ .ignoresSafeArea()
+
+ AppLaunchView(config: .myCamera) {
+ ContentView()
+ }
}
}
}
@@ -434,11 +483,23 @@ struct MyCameraApp: App {
## Troubleshooting
-### White flash before launch screen
+### White/black flash before launch screen
-**Cause:** iOS system launch screen doesn't match your branding colors.
+**Cause:** iOS system launch screen doesn't match your branding colors, or the SwiftUI view hierarchy has a different background.
-**Solution:** Follow [Step 3](#step-3-set-launch-screen-background-color) to add `LaunchBackground` color to your asset catalog and configure the project build settings.
+**Solution:**
+1. Follow [Step 3](#step-3-set-launch-screen-background-color) to add `LaunchBackground` color asset with both light and dark variants
+2. Add `UILaunchScreen` dictionary to Info.plist (Step 3.2)
+3. Wrap `AppLaunchView` in a `ZStack` with `Color.Branding.primary` as the base layer (Step 2)
+4. Ensure the RGB values match **exactly** between the color asset and `Color.Branding.primary`
+
+**Critical:** After any launch screen changes:
+1. Clean build (Cmd+Shift+K)
+2. Delete app from simulator/device completely
+3. Quit and restart the simulator
+4. Build and run fresh
+
+iOS caches the launch screen aggressively.
### Can't find types like `AppIconConfig`
@@ -554,10 +615,13 @@ patternStyle: .none
## Summary Checklist
- [ ] Create `BrandingConfig.swift` with your app's configurations
-- [ ] Add `AppLaunchView` wrapper to your App entry point
-- [ ] Create `LaunchBackground.colorset` in asset catalog matching primary color
-- [ ] Add `INFOPLIST_KEY_UILaunchScreen_BackgroundColor` to project settings
+- [ ] Add `AppLaunchView` wrapper to your App entry point (inside ZStack with base color)
+- [ ] Create `LaunchBackground.colorset` in asset catalog with **both light and dark variants**
+- [ ] Add `UILaunchScreen` dictionary to `Info.plist` with `UIColorName`
+- [ ] Add `INFOPLIST_KEY_UILaunchScreen_BackgroundColor` to project build settings
+- [ ] Verify RGB values match exactly between color asset and `Color.Branding.primary`
- [ ] (Optional) Add debug section to settings with `IconGeneratorView` and `BrandingPreviewView`
+- [ ] Clean build, delete app, and reinstall to test launch screen
- [ ] Build and run in DEBUG mode
- [ ] Generate icon using Icon Generator tool
- [ ] Retrieve icon PNG from device/simulator
diff --git a/Sources/Bedrock/Resources/Localizable.xcstrings b/Sources/Bedrock/Resources/Localizable.xcstrings
index 21ffb43..6cd52d6 100644
--- a/Sources/Bedrock/Resources/Localizable.xcstrings
+++ b/Sources/Bedrock/Resources/Localizable.xcstrings
@@ -65,6 +65,10 @@
"comment" : "The title of the icon generator view.",
"isCommentAutoGenerated" : true
},
+ "Last synced %@" : {
+ "comment" : "A description of the last time the settings were synced, using relative time formatting.",
+ "isCommentAutoGenerated" : true
+ },
"Launch" : {
"comment" : "A tab label for the launch screen preview.",
"isCommentAutoGenerated" : true
@@ -73,10 +77,46 @@
"comment" : "A note explaining that iOS uses a single 1024px icon.",
"isCommentAutoGenerated" : true
},
+ "Open Source Licenses" : {
+ "comment" : "Title of the view that lists open source licenses.",
+ "isCommentAutoGenerated" : true
+ },
+ "QR code" : {
+ "comment" : "A label describing a QR code image.",
+ "isCommentAutoGenerated" : true
+ },
+ "Sign in to iCloud to enable sync" : {
+ "comment" : "Accessibility hint for the iCloud sync settings view, explaining that sync is only available when signed into iCloud.",
+ "isCommentAutoGenerated" : true
+ },
"Size Variants" : {
"comment" : "A heading for the size variants of an app icon.",
"isCommentAutoGenerated" : true
},
+ "Sync Now" : {
+ "comment" : "A button label that triggers a sync action.",
+ "isCommentAutoGenerated" : true
+ },
+ "Sync Settings" : {
+ "comment" : "Title of the iCloud sync settings toggle.",
+ "isCommentAutoGenerated" : true
+ },
+ "Sync settings across all your devices" : {
+ "comment" : "Subtitle for the iCloud sync settings toggle, when sync is available.",
+ "isCommentAutoGenerated" : true
+ },
+ "Synced" : {
+ "comment" : "Text indicating that the user's data is up-to-date and synced.",
+ "isCommentAutoGenerated" : true
+ },
+ "Syncing..." : {
+ "comment" : "Text displayed in the iCloud sync status label when the initial sync is not yet complete.",
+ "isCommentAutoGenerated" : true
+ },
+ "Syncs settings across all your devices via iCloud" : {
+ "comment" : "An accessibility hint for the iCloud sync settings section.",
+ "isCommentAutoGenerated" : true
+ },
"To Export" : {
"comment" : "A section header explaining how to export branding assets.",
"isCommentAutoGenerated" : true
@@ -85,6 +125,10 @@
"comment" : "Instructions for exporting an app icon.",
"isCommentAutoGenerated" : true
},
+ "View on GitHub" : {
+ "comment" : "A label describing an action to view the license on GitHub.",
+ "isCommentAutoGenerated" : true
+ },
"Xcode automatically generates all required sizes from the 1024px source." : {
"comment" : "A footnote explaining that Xcode automatically creates all necessary icon sizes from the original 1024px image.",
"isCommentAutoGenerated" : true