SwiftData serious bug with relationships and CloudKit in iOS 18.0 (Xcode 16 Beta)

Hi guys. Can someone please confirm this bug so I report it? The issue is that SwiftData relationships don't update the views in some specific situations on devices running iOS 18 Beta. One clear example is with CloudKit. I created a small example for testing. The following code creates two @models, one to store bands and another to store their records. The following code works with no issues. (You need to connect to a CloudKit container and test it on two devices)

import SwiftUI
import SwiftData

struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var records: [Record]

    var body: some View {
       NavigationStack {
          List(records) { record in
             VStack(alignment: .leading) {
                Text(record.title)
                Text(record.band?.name ?? "Undefined")
             }
          }
          .toolbar {
              ToolbarItem {
                 Button("Add Record") {
                    let randomNumber = Int.random(in: 1...100)
                    
                    let newBand = Band(name: "New Band \(randomNumber)", records: nil)
                    modelContext.insert(newBand)
                    
                    let newRecord = Record(title: "New Record \(randomNumber)", band: newBand)
                    modelContext.insert(newRecord)
                 }
              }
          }
       }
    }
}
@Model
final class Record {
   var title: String = ""
   var band: Band?

   init(title: String, band: Band?) {
      self.title = title
      self.band = band
   }
}
@Model
final class Band {
   var name: String = ""
   var records: [Record]?

   init(name: String, records: [Record]?) {
      self.name = name
      self.records = records
   }
}

This view includes a button at the top to add a new record associated with a new band. The data appears on both devices, but if you include more views inside the List, the views on the second device are not updated to show the values of the relationships. For example, if you extract the row to a separate view, the second device shows the relationships as "Undefined". You can try the following code.

struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var records: [Record]

    var body: some View {
       NavigationStack {
          List {
             ForEach(records) { record in
                RecordRow(record: record)
             }
          }
          .toolbar {
              ToolbarItem {
                 Button("Add Record") {
                    let randomNumber = Int.random(in: 1...100)
                    
                    let newBand = Band(name: "New Band \(randomNumber)", records: nil)
                    modelContext.insert(newBand)
                    
                    let newRecord = Record(title: "New Record \(randomNumber)", band: newBand)
                    modelContext.insert(newRecord)
                 }
              }
          }
       }
    }
}
struct RecordRow: View {
   let record: Record

   var body: some View {
      VStack(alignment: .leading) {
         Text(record.title)
         Text(record.band?.name ?? "Undefined")
      }
   }
}

Here I use a ForEach loop and move the row to a separate view. Now on the second device the relationships are nil, so the row shows the text "Undefined" instead of the name of the band.

I attached an image from my iPad. I inserted all the information on my iPhone. The first three rows were inserted with the first view. But the last two rows were inserted after I extracted the rows to a separate view. Here you can see that the relationships are nil and therefore shown as "Undefined". The views are not updated to show the real value of the relationship.

This example shows the issue with CloudKit, but this also happens locally in some situations. The system doesn't detect updates in relationships and therefore doesn't refresh the views.

Please, let me know if you can reproduce the issue. I'm using Mac Sequoia 15.1, and two devices with iOS 18.0.

Just a quick idea: Can you access that relationship programmatically? So if you add a button that tries to print that relationship, does that work? Currently there is a bug that @Query does not update the view after an iCloud Sync. I filed a bug report for that. FB14619787 If you can indeed access that relationship you might be able to work around that by using this package (https://github.com/ggruen/CloudKitSyncMonitor) that can update your view whenever the iCloud sync status changes.

Just to echo what @FPST said, this looks like a known bug that has been there for a while. Thanks for being willing to file a new bug report – If you do so, please post your report ID here as well.

For a quick workaround before the issue is fixed from the framework side, you might consider observing .NSPersistentStoreRemoteChange and updating your view from there. This post shows a code example of updating UI by observing NSManagedObjectContextDidSave.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

SwiftData serious bug with relationships and CloudKit in iOS 18.0 (Xcode 16 Beta)
 
 
Q