Post

Replies

Boosts

Views

Activity

How to completely reset SwiftData?
Is it possible to reset SwiftData to a state identical to that of a newly installed app? I have experienced some migration issues where, when I add a new model, I need to reinstall the entire application for the ModelContainer creation to work. Deleting all existing models does not seem to make any difference. A potential solution I currently have, which appears to work but feels quite hacky, is as follows: let _ = try! ModelContainer() modelContainer = try! ModelContainer(for: Student.self, ...) This seems to force out this error CoreData: error: Error: Persistent History (66) has to be truncated due to the following entities being removed: (...) which seems to reset SwiftData. Any other suggestions?
2
0
72
2d
SectionedFetchRequest in SwiftData
With Core Data and SwiftUI we can use @SectionedFetchRequest. Does SwiftData support something similar to @SectionedFetchRequest? For example, I want to create a lazy-loaded list that groups posts by their date. @Model Post { let title: String let dateString: String // YYYY-MM-DD let createdAt: Date } @SectionedFetchRequest( entity: \Post.self, sectionIdentifier: \Post.dateString, sortDescriptors: [\Post.createdAt] ) var postsByDate: SectionedFetchResults ForEach(postsByDate) { section in Section(header: Text(section.id)) { ForEach(section) { post in PostView(post) } } }
1
0
203
Sep ’24
Batch delete many-to-one not working
Doing a batch delete on a many-to-one relationship seems to throw this error CoreData: error: Unhandled opt lock error from executeBatchDeleteRequest Constraint trigger violation: Batch delete failed due to mandatory OTO nullify inverse on Student/school and userInfo { NSExceptionOmitCallstacks = 1; NSLocalizedFailureReason = "Constraint trigger violation: Batch delete failed due to mandatory OTO nullify inverse on Student/school"; "_NSCoreDataOptimisticLockingFailureConflictsKey" = ( ); } If I try to delete the School in the one-to-many relationship, both the school and the students are deleted as expected. However, If I try to delete all students the error is thrown. I would expect all students to be removed, while keeping the School intact. Do SwiftData support this? import XCTest import SwiftData @Model class School { var name: String @Relationship(deleteRule: .cascade, inverse: \Student.school) var students: [Student] = [] init(name: String) { self.name = name } } @Model class Student { var name: String var school: School? init(name: String) { self.name = name } } final class Test: XCTestCase { func testScenario() throws { let config = ModelConfiguration(isStoredInMemoryOnly: true) let modelContainer = try ModelContainer(for: School.self, Student.self, configurations: config ) let context = ModelContext(modelContainer) context.autosaveEnabled = false let school = School(name: "school") context.insert(school) let student1 = Student(name: "1") let student2 = Student(name: "2") context.insert(student1) context.insert(student2) student1.school = school student2.school = school XCTAssertEqual(school.students.count, 2) XCTAssertEqual(student1.school?.id, school.id) XCTAssertEqual(student2.school?.id, school.id) try context.save() let newContext = ModelContext(modelContainer) // try newContext.delete(model: School.self) // This works try newContext.delete(model: Student.self) // This one fails } }
1
2
259
Sep ’24
SwiftData inverse relationship not updating
Given the code below the students array on the school is not being updated. Why? Since the relationship is explicit and non-optional I would expect this to work. import XCTest import SwiftData @Model class School { var name: String @Relationship(deleteRule: .cascade, inverse: \Student.school) var students: [Student] init(name: String, students: [Student]) { self.name = name self.students = students } } @Model class Student { var name: String var school: School init(name: String, school: School) { self.name = name self.school = school } } final class Test: XCTestCase { func testScenario() throws { let modelContainer = try ModelContainer(for: School.self, Student.self ) let context = ModelContext(modelContainer) context.autosaveEnabled = false let school = School(name: "school", students: []) context.insert(school) let student1 = Student(name: "1", school: school) let student2 = Student(name: "2", school: school) context.insert(student1) context.insert(student2) XCTAssertEqual(school.students.count, 2) // XCTAssertEqual failed: ("0") is not equal to ("2") } }
2
0
364
Sep ’24