I came across of something I'm struggling to comprehend. I've got an iOS app based on SwiftUI and SwiftData + CloudKit. I wrote it using Xcode 15 and the target was iOS 17. Everything works fine in this environment, but after upgrading my phone to iOS 18 beta 7 something very strange started to happen with SwiftData on a physical device and in the simulator.
Every time when data is updated, to be precise - when the relationship is modified, the change is reverted after 15 seconds!
I've got the following settings on and nothing can be seen it's going on there in the logs
- -com.apple.CoreData.Logging.stderr 1
- -com.apple.CoreData.CloudKitDebug 1
- -com.apple.CoreData.SQLDebug 1
- -com.apple.CoreData.ConcurrencyDebug 1
Here you are some simplified code extraction:
@Model
final public class Note: Identifiable, Hashable
{
public private(set) var uuid = UUID().uuidString
var notification: Notification?
...
}
@Model
final public class Notification: Identifiable, Hashable
{
var dateId: String = ""
@Relationship(deleteRule: .nullify, inverse: \Note.notification) var notes: [Note]?
init(_ dateId: String) {
self.dateId = dateId
}
}
@ModelActor
final public actor DataModelActor : DataModel
{
public func updateNotification(oldDate: Date, newDate: Date? = nil, persistentModelId: PersistentIdentifier) {
if let note = modelContext.model(for: persistentModelId) as? Note {
updateNotification(oldDate: oldDate, newDate: newDate, note: note)
}
try? self.modelContext.save()
}
private func updateNotification(oldDate: Date? = nil, newDate: Date? = nil, note: Note) {
if let oldDate = oldDate {
let notifications = fetchNotifications()
let oldDateId = NotificationDateFactory.getId(from: oldDate)
// removing the note from the collection related to oldDate
if let notification = notifications.first(where: { $0.dateId == oldDateId }) {
if let notificationNotes = notification.notes {
if let notificationNoteIndex = notification.notes!.firstIndex(of: note) {
notification.notes!.remove(at: notificationNoteIndex)
}
if notification.notes == nil || notification.notes!.isEmpty {
self.modelContext.delete(notification)
}
}
}
}
if let newDate = newDate, newDate > Calendar.current.startOfToday() {
// adding to a new collection related to newDate
let notifications = fetchNotifications()
let newDateId = NotificationDateFactory.getId(from: newDate)
if let notification = notifications.first(where: { $0.dateId == newDateId }) {
note.notification = notification
} else {
let notification = Notification(newDateId)
note.notification = notification
}
}
}
}
Spreading save method here and there does not help :(
I've used Core Data Lab software to look into database and I can clearly see data changes are reverted for relationship property.
Example:
In Notification database there is one element:
2024-08-26 (3)
with 3 notes attached. I modified one note to send notification on 2024-08-27. Changes in database reflects situation correctly showing:
- 2014-08-26 (2)
- 2024-08-27 (1)
BUT!!! After 15 seconds doing noting database looks like this:
- 2024-08-26 (3)
- 2024-08-27 (0)
All changes were reverted and all notes are still attached to the same date as they were at the first place.
Any thoughts?