SwiftData:如何检测 CloudKit 何时同步(或即将同步)新数据

问题描述 投票:0回答:1

有两件事:

  • 如何检测带有 CloudKit 的 SwiftData 何时完成从其他地方同步新数据?
  • 如何检测是否有更改仍需要同步?

一些背景: 目前似乎没有办法避免启用 CloudKit 的 SwiftData 中的重复项,显然唯一的方法是手动删除重复项。

“理想情况下”,我想在 CloudKit 同步完成后执行此操作。和/或避免在启动应用程序时 CloudKit 完成同步之前获取新数据。

swift core-data swift-data
1个回答
0
投票

事实上,没有办法正确执行此操作,也没有直接的方法来检测某些内容是否已实际同步或即将同步(除了监听 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
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.