Post

Replies

Boosts

Views

Activity

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
192
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
249
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
336
Sep ’24