Post

Replies

Boosts

Views

Activity

Reply to SwiftData + CKSyncEngine
Thanks for the reply. I've been trying to get CKSyncEngine working with SwiftData. Since you don't any sample code, here's my code and some questions about it. CKSyncEngineDelegate has a function called "handleEvent". In that function I handle the "fetchedRecordZoneChanges" event amongst other events. Here's my function to handle that event (it's basically copy paste from the sample app): func handleFetchedRecordZoneChanges(_ event: CKSyncEngine.Event.FetchedRecordZoneChanges) { guard let localContainer else { return } let newContext = ModelContext(localContainer) let localHabits = SwiftDataPersistence.fetch(FetchDescriptor<Habit>(), predicate: nil, sortBy: [], fetchLimit: nil, context: newContext) for modification in event.modifications { // The sync engine fetched a record, and we want to merge it into our local persistence. let serverHabit = modification.record let serverHabitID = serverHabit.recordID.recordName // If we already have this object locally, let's merge the data from the server. if let localHabit = localHabits.first(where: { habit in habit.identifier == serverHabitID }) { localHabit.mergeFromServerData(serverHabit) localHabit.setLastKnownRecordIfNewer(serverHabit) } // Otherwise, let's create a new local object. else { let newHabit = Habit(record: serverHabit) newContext.insert(newHabit) } } for deletion in event.deletions { // TO DO } // If we had any changes, let's save to disk. if !event.modifications.isEmpty || !event.deletions.isEmpty { SwiftDataPersistence.save(newContext) NotificationCenter.default.post(name: newContextDidSaveNotification, object: nil) } } Last line of code: I'm sending a notification to my SwiftUI view (that shows habits) to fetch edited/new habits. Here's my view code: struct HabitsListView: View { @State private var habits = [Habit]() @Environment(\.modelContext) private var context var body: some View { LazyVStack(alignment: .leading, spacing: 8) { ForEach(habits) { habit in HabitRow(habit) } } .onNewContextDidSave { fetchHabits() } } func fetchHabits() { self.habits = SwiftDataPersistence.fetch(FetchDescriptor<Habit>(), predicate: nil, sortBy: [SortDescriptor(\Habit.name)], fetchLimit: nil, context: context) } } This approach seems to work, but it's not ideal and I'm not sure it's a correct way to do it. It works with only 1 custom notification, but I ran into problems when I added more notifications - then the notifications stopped firing or the view didn't catch them. But my main question at this moment is: How to get @Query to update my habits list, so I don't have to manually fetch habits at every change. I would like to use a view like this: struct HabitsListView: View { @Query private var habits: [Habit] var body: some View { LazyVStack(alignment: .leading, spacing: 8) { ForEach(habits) { habit in HabitRow(habit) } } } } Thanks! Martin
3w