// // CloudSyncMonitor.swift // Haru_Danim // // CloudKit 원격 변경 반영 (메인 앱 전용) // - SwiftData의 CloudKit 스토어는 원격 가져오기·다른 프로세스(위젯 인텐트)의 쓰기 때 // NSPersistentStoreRemoteChange 알림을 올린다. 이를 받아 위젯 타임라인·워치 스냅숏· // 라이브 액티비티를 갱신해, 다른 기기에서 바뀐 데이터가 위젯에 바로 반영되게 한다. // - 가져오기 중에는 알림이 짧은 간격으로 여러 번 오므로 디바운스로 한 번만 갱신한다. // import CoreData import SwiftData import WidgetKit @MainActor final class CloudSyncMonitor { static let shared = CloudSyncMonitor() private var observer: (any NSObjectProtocol)? private var refreshTask: Task? /// 앱 시작 시 1회 호출. 이후 원격 변경이 올 때마다 디바운스 갱신을 예약한다. func start(container: ModelContainer) { guard observer == nil else { return } observer = NotificationCenter.default.addObserver( forName: .NSPersistentStoreRemoteChange, object: nil, queue: nil ) { _ in Task { @MainActor in CloudSyncMonitor.shared.scheduleRefresh(container: container) } } } private func scheduleRefresh(container: ModelContainer) { refreshTask?.cancel() refreshTask = Task { @MainActor in // CloudKit 가져오기 묶음이 끝나길 기다렸다가 한 번만 갱신 try? await Task.sleep(for: .seconds(2)) guard !Task.isCancelled else { return } // 다른 기기에서 세션이 시작/종료됐을 수 있으므로 라이브 액티비티부터 맞춘다 LiveActivityManager.sync(context: container.mainContext) WidgetCenter.shared.reloadAllTimelines() WatchSyncManager.shared.pushSnapshot() } } }