- 목표 하루 진행률은 오늘이 수행일인 다짐만 모수로 계산 (요일·날짜 지정으로 오늘 쉬는 다짐은 분모에서 제외, QuestProgress.isScheduled 신설) - 오늘 수행할 다짐이 하나도 없는 날은 0% 대신 100%(완료 상태)로 표기 - 주간/월간 진행률은 기존대로 전체 다짐 기준 유지 - 이벤트 기반 위젯 새로 고침: 앱 내 모든 핵심 Mutation(측정 시작/종료, 횟수 추가, 기록 추가·수정·삭제, 행동·꼬리표·목표·다짐 CRUD, 순서 변경, 목표 상태 변경)의 끝단에서 DataChange.commit() 호출 — 저장 즉시 확정 후 Live Activity·위젯 타임라인·워치 스냅숏을 한 번에 동기화 - 주기적 백그라운드 새로 고침 없이 변경 시점에만 갱신해 WidgetKit 업데이트 예산 절약 (타이머 표시는 기존 Text(style: .timer)로 시스템이 자체 렌더링하므로 타임라인 소모 없음) - 하루 시작 시간·주 시작 요일 설정 변경 시에도 위젯 집계 갱신 - 시뮬레이터 검증: 월·수·금 다짐이 있는 목표의 토요일 하루 진행률이 33%가 아닌 50%(오늘 수행 다짐 2개 평균)로 표시됨 확인 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
24 lines
910 B
Swift
24 lines
910 B
Swift
//
|
|
// DataChange.swift
|
|
// Haru_Danim
|
|
//
|
|
// 앱 안에서 데이터가 바뀌는 모든 Mutation의 끝단에서 호출하는 공통 갱신 지점.
|
|
// 주기적 백그라운드 새로 고침 대신 변경 이벤트 시점에만 위젯 타임라인을 갱신해
|
|
// WidgetKit 업데이트 예산을 아낀다. (시리/위젯 인텐트 경로는 IntentStore.commit()이 같은 역할)
|
|
//
|
|
|
|
import SwiftData
|
|
import WidgetKit
|
|
|
|
@MainActor
|
|
enum DataChange {
|
|
/// 저장을 즉시 확정(위젯 확장이 같은 App Group 저장소를 읽으므로 autosave를 기다리지 않음)하고
|
|
/// Live Activity → 위젯 타임라인 → 워치 스냅숏 순으로 동기화한다.
|
|
static func commit(context: ModelContext) {
|
|
try? context.save()
|
|
LiveActivityManager.sync(context: context)
|
|
WidgetCenter.shared.reloadAllTimelines()
|
|
WatchSyncManager.shared.pushSnapshot()
|
|
}
|
|
}
|