iPadOS 18 Beta and SwiftData issues

I had a series of @Model classes with some mandatory attributes and some optional.

Pre-move to 18, everything was working fine. After the migration, it reports that every single non-Optional attribute is nil upon trying to save.

The error is CoreData related but not sure if its in the Core layer or Swift layer.

Sample error (with app data removed) is :

SwiftData.DefaultStore save failed with error: Error Domain=NSCocoaErrorDomain Code=1560 "Multiple validation errors occurred."

Error Domain=NSCocoaErrorDomain Code=1570 \"%{PROPERTY}@ is a required value.\" UserInfo={NSValidationErrorObject=<NSManagedObject: 0x30388b2a0>

NSLocalizedDescription=%{PROPERTY}@ is a required value., NSValidationErrorKey=systemName, NSValidationErrorValue=null}"

I have modified the code to provide default values for all constructors in an attempt to see a difference, but get the same errors

Same issue!

I get this error too, so the Relation isn't handled properly, so I set it through the association object, and the error goes away:

@Model class School {
  @Relationship(deleteRule: .cascade)
  var students: [Student] = []
  
  init() {}
}

@Model class Student {
  @Relationship(inverse: \School.students)
  var school: School
  
  init(school: School) {
    self.school = school
  }
}

let school = School()
modelContext.insert(school)

let student = Student(school: school)
school.students.append(student) // <-- this works!
try modelContext.save()

I have the exact same issue and just filed a report FB15146262. iOS 18 doesn't set the one-to-many relationship from the 'one' side, i.e. setting student.school = school will actually keep the relationship at nil and can't be saved into context.

This is visible in the debugger error message:

SwiftData.DefaultStore save failed with error: Error Domain=NSCocoaErrorDomain Code=1570 "%{PROPERTY}@ is a required value." UserInfo={NSValidationErrorObject=<NSManagedObject: 0x60000211ec60> (entity: Student; id: 0x600000223380 <x-coredata://3B392729-2729-4812-B567-647032714A50/Student/t6F58A598-9DC2-4927-A418-8D37D760FC072>; data: { name = jack; school = nil; }), NSLocalizedDescription=%{PROPERTY}@ is a required value., NSValidationErrorKey=school, NSValidationErrorValue=null}

The workaround by @Rainbowql with additionally calling append fixes this issue on iOS 18 but causes the app to crash on iOS 17, because the relationship is already set normally before calling append. On iOS 17, you will get:

SwiftData/PersistentModel.swift:540: Fatal error: Unsupported relationship key path ReferenceWritableKeyPath<Student, School>

The workaround I ended up implementing is wrapping 'append' with available:

if #available(iOS 18.0, *) {
    school.students.append(student)
}

** Interestingly, after you add this workaround and launch the app once, you can sometimes remove it and it will work fine without the append on iOS 18 just like on 17. This can still work without append even after deleting the app and reinstalling it. **

here is the full code to try this on the starter project.

import SwiftUI
import SwiftData

@Model class School {
    @Relationship(inverse: \Student.school)
    var students: [Student] = []
    
    init() {}
}

@Model class Student {
    @Relationship
    var school: School
    var name: String
    
    init(school: School, name: String) {
        self.school = school
        self.name = name
    }
}

@main
struct SwiftDataRelationshipBugApp: App {
    var sharedModelContainer: ModelContainer = {
        do {
            return try ModelContainer(for: School.self , Student.self,
                                      configurations: ModelConfiguration(isStoredInMemoryOnly: false))
        } catch {
            fatalError("Could not create ModelContainer: \(error)")
        }
    }()
    
    func addStudents(){
        let school = School()
        sharedModelContainer.mainContext.insert(school)
        let student = Student(school: school, name: "jack")
        sharedModelContainer.mainContext.insert(student)
        if #available(iOS 18.0, *) { 
            school.students.append(student) // this alone will not work on iOS 17
        }
        if sharedModelContainer.mainContext.hasChanges{
            do{
                try sharedModelContainer.mainContext.save()
            }catch{
                fatalError("can't save chnages")
            }
        }
    }
    
    init() {
        addStudents()
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(sharedModelContainer)
    }
}
iPadOS 18 Beta and SwiftData issues
 
 
Q