Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>

This commit is contained in:
Matt Bruce 2026-01-16 16:02:11 -06:00
parent 9cd1652727
commit d97f7e8b91
2 changed files with 43 additions and 10 deletions

View File

@ -6,15 +6,36 @@ A sample iOS app demonstrating the LocalData package capabilities for secure, ty
This app provides interactive demos for all LocalData storage options:
| Tab | Demo | Storage Domain |
|-----|------|----------------|
| **Defaults** | Save/load/remove values | UserDefaults |
| Screen | Demo | Storage Domain |
|--------|------|----------------|
| **UserDefaults** | Save/load/remove values | UserDefaults |
| **Keychain** | Secure credentials with biometrics | Keychain |
| **Files** | User profiles with Codable models | File System |
| **Encrypted** | Encrypted logs (AES or ChaCha20) | Encrypted File System |
| **Sync** | Platform availability & sync policies | Multiple |
| **File Storage** | User profiles with Codable models | File System |
| **Encrypted Storage** | Encrypted logs (AES or ChaCha20) | Encrypted File System |
| **Platform Sync Lab** | Platform availability & sync policies | Multiple |
The project also includes a watchOS companion app target for watch-specific demos.
The watch app displays the synced user profile and the syncable setting from the Platform Sync Lab.
On iPhone launch and when the watch becomes available, the app re-sends any syncable keys so the watch updates without manual re-entry.
The watch app also requests a sync on launch when the iPhone is reachable.
## Watch Sync Handshake
This sample uses a launch-order-safe handshake so either app can start first:
1. **Watch app launches** → sends a `request_sync` message (or queues it if the iPhone is unreachable).
2. **iOS app receives the request** → replies with a snapshot of current syncable keys and updates `applicationContext`.
3. **Watch app applies the snapshot** → UI updates immediately.
This avoids requiring users to remember which app to open first.
### Where the Logic Lives
- iOS WCSession + handshake: `SecureStorageSample/SecureStorageSample/Services/WatchConnectivityService.swift`
- Bootstrap on launch: `SecureStorageSample/SecureStorageSample/SecureStorageSampleApp.swift`
- Sync policy UI lab: `SecureStorageSample/SecureStorageSample/Views/PlatformSyncDemo.swift`
- Watch WCSession + request: `SecureStorageSample/SecureStorageSample Watch App/Services/WatchConnectivityService.swift`
- Watch payload handlers: `SecureStorageSample/SecureStorageSample Watch App/Services/Handlers/`
## Requirements

View File

@ -4,7 +4,7 @@ A watchOS companion app demonstrating data synchronization with the iOS app usin
## Overview
This watch app receives `UserProfile` data synced from the paired iPhone via `WCSession.updateApplicationContext`. It does **not** use LocalData directly for storage—instead, it displays synced data in memory.
This watch app receives `UserProfile` data and the syncable setting from the paired iPhone via WatchConnectivity. It does **not** use LocalData directly for storage—instead, it displays synced data in memory.
## Architecture
@ -12,6 +12,8 @@ This watch app receives `UserProfile` data synced from the paired iPhone via `WC
SecureStorageSample Watch App/
├── ContentView.swift # Displays synced profile data
├── SecureStorageSampleApp.swift
├── Design/
│ └── WatchDesignConstants.swift
├── Protocols/
│ └── WatchDataHandling.swift # Protocol for payload handlers
├── State/
@ -20,15 +22,25 @@ SecureStorageSample Watch App/
├── WatchConnectivityService.swift
└── Handlers/
└── UserProfileWatchHandler.swift
└── SyncableSettingWatchHandler.swift
```
## Data Flow
1. **iOS app** calls `SyncHelper` when storing data with `syncPolicy: .automaticSmall` or `.manual`
2. `SyncHelper` sends data via `WCSession.updateApplicationContext`
1. **Watch app** requests a sync when it launches or becomes reachable
2. **iOS app** replies with a snapshot of syncable keys and updates `applicationContext`
3. **Watch app** receives context in `WatchConnectivityService`
4. The service dispatches each payload key to its registered `WatchDataHandling` handler
5. `UserProfileWatchHandler` decodes the profile and updates `WatchProfileStore`
5. Handlers decode values and update `WatchProfileStore`
## Launch-Order-Safe Sync
The watch app handles both cases:
- If the iPhone is reachable, it sends a `request_sync` message and applies the reply payload.
- If the iPhone is not reachable, it queues a request with `transferUserInfo` and shows a badge.
This ensures users do not need to launch the apps in a specific order.
## Adding New Sync Payloads