464fbb2bad
App de watchOS de solo consulta: resumen de cartera (total, cambio del mes y mayores posiciones), objetivos con su progreso y estado del check-in con la racha. Toda la edición sigue en el iPhone. Complicaciones (accessoryCircular / Rectangular / Inline / Corner): valor total de la cartera, progreso del objetivo más cercano a cumplirse y racha + estado del check-in. Datos: los App Groups no se comparten entre iOS y watchOS, así que el reloj no puede leer el store de CoreData que lee el widget de iOS. En su lugar, WatchSyncService construye un WatchPortfolioSnapshot ligero y lo envía como application context de WatchConnectivity, enganchado a CoreDataStack.refreshWidgetData() — el mismo punto que refresca el widget de iOS, así que cualquier repositorio que toque datos refresca el reloj. WatchDataStore lo cachea en el App Group del watch (WatchSnapshotCache) y recarga las timelines; la extensión de complicaciones solo lee ese caché. Proyecto: dos targets nuevos (watchOS app + widget extension) con grupos sincronizados de Xcode 16; Shared/ pertenece a la app de watch y se comparte con la app de iOS y el widget mediante exception sets, el mismo mecanismo que ya usaba el widget de iOS para el modelo de CoreData. Scheme compartido PortfolioJournalWatch. Localización propia por target en los 7 idiomas. Verificado: compilan los tres targets, la app de watch queda embebida en Watch/ con la extensión en PlugIns/, y en el par de simuladores iPhone 17 Pro Max + Apple Watch Series 11 el reloj recibe y muestra el snapshot enviado por el iPhone. 10 tests nuevos del payload. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YcDn5ccuRFV83q7xWWokBT
29 lines
1.1 KiB
Swift
29 lines
1.1 KiB
Swift
import Foundation
|
|
|
|
/// On-watch cache of the last snapshot received from the iPhone.
|
|
///
|
|
/// The watch app writes it; the complication extension reads it. They are
|
|
/// separate processes, so the App Group container is what lets them share —
|
|
/// with a fallback to the process defaults so the app still shows data even if
|
|
/// the App Group entitlement is not in place yet.
|
|
enum WatchSnapshotCache {
|
|
|
|
private static var sharedDefaults: UserDefaults? {
|
|
UserDefaults(suiteName: WatchPortfolioSnapshot.appGroupIdentifier)
|
|
}
|
|
|
|
static func save(_ snapshot: WatchPortfolioSnapshot) {
|
|
guard let data = snapshot.encoded() else { return }
|
|
let key = WatchPortfolioSnapshot.payloadKey
|
|
sharedDefaults?.set(data, forKey: key)
|
|
UserDefaults.standard.set(data, forKey: key)
|
|
}
|
|
|
|
static func load() -> WatchPortfolioSnapshot? {
|
|
let key = WatchPortfolioSnapshot.payloadKey
|
|
let data = sharedDefaults?.data(forKey: key) ?? UserDefaults.standard.data(forKey: key)
|
|
guard let data else { return nil }
|
|
return WatchPortfolioSnapshot.decoded(from: data)
|
|
}
|
|
}
|