I have SwiftData configured with CloudKit iCloud sync, and the sync is initiated only when the application is launched or the scene phase is changed. CloudKit remote notifications are not received while the application is running; instead, each sync remote notification is sent to app only upon a scene phase change, such as transitioning from the Home Screen to the Main Screen and returning. Subsequently, the application syncs with the most recent data. I have observed other individuals who have implemented a similar sync but with diffrent data, where a record is added on one device, and it appears on the other device without the need to change the scene phase. Currently, I am using two physical devices: a Mac and an iPhone. The Mac is running macOS 15.1 beta 2, while the iPhone is running iOS 18.0 beta 6 Xcode Version is 15.1.
-
CloudKit Sync Issue: CloudKit remote notifications to update data only appear when the app’s scene phase changes, not when the app is running.
-
Sync Trigger: To sync again, the scene phase needs to be changed to trigger the sync.
-
App uses @Query macro with different predicates like
@Query(filter: #Predicate<Payment>{ $0.isPinned && $0.renewalID != 1000 }, sort: \.pinnedOrder, animation: .smooth) private var paymentsData: [Payment]
@Query var data: [Payment] and the predicate is made in the initializer of the view.
init(searchText: String) {
self.searchText = searchText
let billsPredicate = #Predicate<Payment>{$0.renewalID != 1000 }
_bills = Query(filter: billsPredicate, animation: .smooth)
let pinnedPredicate = #Predicate<Payment>{
if searchText.isEmpty{
$0.isPinned && $0.renewalID != 1000
}else{
$0.isPinned && $0.renewalID != 1000 && $0.name.localizedStandardContains(searchText)
}
}
_pinnedBills = Query(filter: pinnedPredicate, sort: \.pinnedOrder, animation: .smooth)
let notPinnedPredicate = #Predicate<Payment>{
if searchText.isEmpty{
!$0.isPinned && $0.renewalID != 1000
}else{
!$0.isPinned && $0.renewalID != 1000 && $0.name.localizedStandardContains(searchText)
}
}
_notPinnedBills = Query(filter: notPinnedPredicate, sort: \.name, animation: .smooth)
}
*The application has minimal deployment targets set to iOS 17.0, macOS Sonoma 14.0, watchOS 10.0, and visions 1.1.
-
When I tested it I used two builds just compiled in Xcode or two builds downloaded from TestFlight
-
All CloudKit Container changes are deployed to production and app bundle id is like app.SomeApp and container id is iCloud.app.SomeApp
*I verified the functionality by adding a record on one device and observing it appearance on another device. Alternatively, I modified record details, such as the name, in the CloudKit Console and watch for changes without app restart. Every time scene phase is needed to trigger sync and see changes.
What actions can I take to ensure data synchronization or download occurs when the application is in use? (scenePhase is .active )
The issue you described can be that:
- SwiftData + CloudKit doesn't import the change from the CloudKit server.
- SwiftData + CloudKit does import the change, but
Query
doesn't update the data.
I believe these were discussed in the following posts, respectively:
Best,
——
Ziqiao Chen
Worldwide Developer Relations.