CoreStore
                                
                                 CoreStore copied to clipboard
                                
                                    CoreStore copied to clipboard
                            
                            
                            
                        [CoreStore: Error] NSManagedObjectContext+Transaction.swift:203 saveAsynchronouslyWithCompletion
I am using ImportUniqueObjects extension to import data from the server. If the Store is empty import works but if there is a previous data, following error comes
⚠️ [CoreStore: Error] NSManagedObjectContext+Transaction.swift:203 saveAsynchronouslyWithCompletion
  ↪︎ Failed to save 'NSManagedObjectContext'.
    (CoreStore.CoreStoreError) .internalError (
    .errorDomain = "com.corestore.error";
    .errorCode = 4;
    .NSError = (
        .domain = "NSCocoaErrorDomain";
        .code = 1560;
        .userInfo = 1 key-value(s) [
 "Error Domain=NSCocoaErrorDomain Code=1570 \"The operation couldn\U2019t be completed. (Cocoa error 1570.)\" UserInfo={NSValidationErrorObject=<KargoDetailCD: 0x600000289fb0> 
(entity: KargoDetailCD; id: 0xd000000004040002 <x-coredata://8E3ADB60-D46E-466A-91C6-840A45557571/KargoDetailCD/p257> ; 
data: {\n    date = \"2015-10-13 06:50:00 +0000\";\n    
lat = nil;\n    location = \"\";\n    
long = nil;\n    
message = \"Message\";\n    
parent = nil;\n    
status = 0;\n}), 
NSValidationErrorKey=parent, NSLocalizedDescription=The operation couldn\U2019t be completed. (Cocoa error 1570.)}",
I know code 1560 is validation error but why it works in the first time but not the second time puzzles me. Error code also shows that parent is nil.
Here is the relevant models
Storage.stack.perform(asynchronous: { transaction in
    try! transaction.importUniqueObjects(Into(KargoCD.self), sourceArray: kargos)
}, success: { done in
    print("DoneStore :\(done)")
}, failure: { error in
    print("MyError CoreStore: \(error)")
})
class KargoCD: NSManagedObject {
    @NSManaged var expected: Date?
    @NSManaged var extra: String?
    @NSManaged var finishDate: Date?
    @NSManaged var isDelivered: NSNumber
    @NSManaged var name: String?
    @NSManaged var receiver: String?
    @NSManaged var sender: String?
    @NSManaged var slug: String
    @NSManaged var startDate: Date?
    @NSManaged var trackingID: String
    @NSManaged var trackingNumber: String
    @NSManaged var updateDate: Date?
    @NSManaged var detail: NSOrderedSet
}
class KargoDetailCD: NSManagedObject {
    @NSManaged var message: String?
    @NSManaged var date: Date?
    @NSManaged var location: String?
    @NSManaged var status: NSNumber
    @NSManaged var lat: NSNumber?
    @NSManaged var long: NSNumber?
    @NSManaged var parent: KargoCD
}
extension KargoDetailCD:ImportableObject {
    typealias ImportSource = KargoDetail
    func didInsert(from source: KargoDetail, in transaction: BaseDataTransaction) throws {
        self.message = source.message
        self.date = source.date
        self.location = source.location
        self.status = NSNumber(value: source.status.rawValue)
    }
}
extension KargoCD:ImportableUniqueObject {
    typealias ImportSource = Kargo
    // MARK: ImportableUniqueObject
    typealias UniqueIDType = String
    static var uniqueIDKeyPath: String {
        return #keyPath(KargoCD.trackingID)
    }
    
    static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool {
        return true
    }
    
    static func shouldUpdate(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool {
        return true
    }
    
    static func uniqueID(from source: Kargo, in transaction: BaseDataTransaction) throws -> String? {
        return source.trackingID
    }
    
    func update(from source: Kargo, in transaction: BaseDataTransaction) throws {
        self.name = source.name
        self.trackingNumber = source.trackingNumber
        self.trackingID = source.trackingID
        self.slug = source.slug
        self.startDate = source.startDate
        self.updateDate = source.updateDate
        self.finishDate = source.finishDate
        self.expected = source.expectedDate
        self.isDelivered = source.isDelivered as NSNumber
        self.sender = source.sender
        self.receiver = source.receiver
        self.extra = source.extra
        let details =  try transaction.importObjects(Into(KargoDetailCD.self), sourceArray: source.details)
        self.detail = NSOrderedSet(array: details)
    }
}
@tosbaha If I'm interpreting your error message correctly,
NSValidationErrorObject=<KargoDetailCD: 0x600000289fb0> ... NSValidationErrorKey=parent
I think the issue is that the moment this line is executed,
self.detail = NSOrderedSet(array: details)
the old KargoDetailCD instances get their KargoDetailCD.parent set to nil. You probably have a "required" constraint for the KargoDetailCD.parent relation.
Either you remove this requirement, or you delete the old details before you assign new ones. I would recommend the latter so your sqlite file don't get polluted with orphaned records.
Thanks a lot! I really appreciate your dedication to this project. I added below code and error is gone.
if let deletable = self.detail.array as? [KargoDetailCD] {
    transaction.delete(deletable)
 }
PS: It is not related to this question directly, but is there a way to have a Uniqueness by using multiple fields. Because for this user case, I don't have any ID to differentiate. Something like Hashable protocol maybe?