有两件事:
一些背景: 目前似乎没有办法避免启用 CloudKit 的 SwiftData 中的重复项,显然唯一的方法是手动删除重复项。
“理想情况下”,我想在 CloudKit 同步完成后执行此操作。和/或避免在启动应用程序时 CloudKit 完成同步之前获取新数据。
事实上,没有办法正确执行此操作,也没有直接的方法来检测某些内容是否已实际同步或即将同步(除了监听 CoreData 更改并尝试排除那些听起来像噩梦的更改之外)。
我所做的工作是在应用程序启动后延迟刷新直到初始 iCloud 同步完成,这有望避免创建重复项的主要原因。
@Observable class RefreshManager {
@MainActor var isSyncing: Bool = false
@ObservationIgnored var cancellables: Set<AnyCancellable> = []
@ObservationIgnored var syncDoneTask: Task<(), Never>?
init() {
NotificationCenter.default.publisher(for: NSPersistentCloudKitContainer.eventChangedNotification)
.sink { [weak self] notification in
guard let self else { return }
if let event = notification.userInfo?[NSPersistentCloudKitContainer.eventNotificationUserInfoKey]
as? NSPersistentCloudKitContainer.Event {
syncDoneTask?.cancel()
if event.endDate == nil {
// starting some sync event
Task { @MainActor in
self.isSyncing = true
}
} else {
// event done
syncDoneTask = Task {
do {
// Wait for no more sync events to show up
try await Task.sleep(s: 3)
await self.handleIcloudSyncDone()
} catch {
// task cancelled
}
}
}
}
}
.store(in: &cancellables)
}
deinit {
cancelSyncListener()
}
func cancelSyncListener() {
cancellables.removeAll()
}
func handleIcloudSyncDone() async {
Task { @MainActor in
self. isSyncing = false
}
// Make sure this function is not called repeatedly for future updates
cancelSyncListener()
// do something after sync is done
}
}