Commit Graph

3 Commits

Author SHA1 Message Date
Arkadiusz Fal
da6c949f51 Resume CloudKit sync from persisted state instead of full re-fetch
Previously CKSyncEngine was created with nil state serialization on
every launch, replaying the entire zone change history (hundreds of
merge/delete log lines and re-downloads each start). Now the saved
state is loaded so launches only fetch changes since the last session.

To make incremental sync safe:
- Clear persisted state once when the record schema version increases,
  so records previously skipped as unsupported get re-delivered after
  an app update.
- Handle remote zone deletion in fetchedDatabaseChanges by recreating
  the zone and re-uploading local data, instead of leaving sync dead.

Account change and manual Refresh Sync still clear the state and force
a full fetch as before.
2026-06-23 23:54:40 +02:00
Arkadiusz Fal
ba33823048 Run CloudKit record mapping on the main actor to fix SwiftData race
CloudKitRecordMapper was a standalone actor, so 'await recordMapper.toCKRecord'
from the @MainActor sync engine hopped off the main actor and read live
SwiftData @Model properties (e.g. LocalPlaylistItem.authorName) from the wrong
executor. SwiftData models are bound to the main ModelContext and are not
thread-safe, so this raced the backing store and crashed with EXC_BAD_ACCESS.

Make the mapper @MainActor (it must touch main-isolated models regardless) and
drop the now-redundant awaits. Fixes the crash for all synced model types.

Fixes an EXC_BAD_ACCESS seen in TestFlight build 261.
2026-05-13 20:56:03 +02:00
Arkadiusz Fal
100df744d9 Yattee v2 rewrite 2026-04-18 20:37:24 +02:00