I have to add types of devices to a manufacturer. The manufacturer name should be unique.
In the relationship i have one to many from the manufacturers to the type and in the opposite I have the relationship many to one from the types to the manufacturers.
Now I try to add with this example some values:
struct ManufacturerListView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(sortDescriptors: []) var manufacturers: FetchedResults<ManufacturerEntity>
var body: some View {
VStack {
List {
ForEach(manufacturers, id: \.self) { manufacturer in
Section(manufacturer.wrapedName) {
ForEach(manufacturer.typesArray, id: \.self) { type in
Text(type.wrappedNname)
}
}
}
}
Button("Add Examples") {
let type1 = TypeEntity(context: viewContext)
type1.name = "T2"
type1.manufacturer = ManufacturerEntity(context: viewContext)
type1.manufacturer?.name = "Tormek"
let type4 = TypeEntity(context: viewContext)
type4.name = "T8"
type4.manufacturer = ManufacturerEntity(context: viewContext)
type4.manufacturer?.name = "Tormek"
let type5 = TypeEntity(context: viewContext)
type5.name = "sh222"
type5.manufacturer = ManufacturerEntity(context: viewContext)
type5.manufacturer?.name = "Scheppach"
do {
let done = try viewContext.save()
} catch let error {
let errortext = error.localizedDescription
print(errortext)
}
}
}
}
}
But it seems that the manufacturer would added seperate and it be not used as unique.
Where is my mistake? I can't see it.
I got the error:
Error Domain=NSCocoaErrorDomain Code=133021 "(null)" UserInfo={NSExceptionOmitCallstacks=true, conflictList=( "NSConstraintConflict (0x600000012d80) for constraint (\n name\n): database: (null), conflictedObjects: (\n \"0x6000015353c0 \",\n \"0x6000015350e0 \"\n)" )}
It's because of this line:
try? viewContext.save()
This throws an error, but you don't handle it, so you end up with erroneous results. Your code creates an erroneous situation but ignores the error by using try?
.
When you have a uniqueness constraint like this and your code violates that constraint (as it does here), Core Data has conflicting requirements that need to be resolved somehow.
If you made it a try
instead of a try?
and you caught the error, you'd find that the error is an NSConstraintConflict
that describes the conflict your code creates. You could have code in the catch
block to resolve the conflict.
You could also choose a merge policy for your context, which would make it resolve the conflict automatically. There are several automatic options-- see the documentation for NSMergePolicy
to chose one.