iOS Core Data - Saving the similar object is not overriding the old object

270 views Asked by At

I'm new with Core Data and I'm having an issue with saving Objects. I want to have a behavior in which I can save the same Object(for me it means it has the same id - Primary Key) and it will not create a new entry for the same id.

I believe it is similar to OnConflictStrategy.REPLACE in Android ROOM which is using sqlite as well.

Here is my add post method to Core Data. I'm using merge policy but it is still not working.

    static func addPost(post:Post){
        guard let context = context else {
            print("post add error with context core data")
            return
        }
        context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
        let p = PostDao(context: context)
        p.id = post.id
        p.username = post.username
        p.title = post.title
        p.photo = post.photo
        p.location = post.location
        p.contactPhone = post.contactPhone
        p.isPostDeleted = post.isPostDeleted!
        p.postDescription = post.postDescription
        p.lastUpdated = post.lastUpdated
        p.contactEmail = post.contactEmail
        
        do{
            try context.save()
        }catch let error as NSError{
            print("post add error core data\(error) \(error.userInfo)")
        }
    }
class Post{
    
    public var id: String? = ""
    public var title: String? = ""
    public var username: String? = ""
    public var postDescription: String? = ""
    public var photo: String? = ""
    public var location: String? = ""
    public var contactPhone: String? = ""
    public var contactEmail: String? = ""
    public var isPostDeleted: Bool? = false
    public var lastUpdated:Int64 = 0
    
    init(){}
    
    init(post:PostDao){
        id = post.id
        title = post.title
        postDescription = post.postDescription
        username = post.username
        photo = post.photo
        isPostDeleted = post.isPostDeleted
        lastUpdated = post.lastUpdated
        location = post.location
        contactPhone = post.contactPhone
        contactEmail = post.contactEmail
    }
    
}

extension PostDao {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<PostDao> {
        return NSFetchRequest<PostDao>(entityName: "PostDao")
    }

    @NSManaged public var id: String?
    @NSManaged public var title: String?
    @NSManaged public var username: String?
    @NSManaged public var photo: String?
    @NSManaged public var postDescription: String?
    @NSManaged public var location: String?
    @NSManaged public var contactPhone: String?
    @NSManaged public var contactEmail: String?
    @NSManaged public var isPostDeleted: Bool
    @NSManaged public var lastUpdated: Int64

}

extension PostDao : Identifiable {

}

My DataModel:

Data Model

1

There are 1 answers

0
Tom Harrington On

Core Data has no idea what a primary key is, so it doesn't care if you have duplicate values for id. It's not SQL, and thinking in SQL terms is a mistake.

If you want to prevent duplicate IDs, you need to add a uniqueness constraint in the model editor. In your screenshot, on the right, where it says "Constraints", click the "+" button. That will add a line in the table. Edit the line to add the property you want to be unique-- just id, nothing else. Core Data will then use that as a unique property. If you create a new object with the same id, Core Data will use the merge policy to make sure you don't get a duplicate id.

Keep in mind that the uniqueness constraint is not just another name for "primary key". It works differently, for different reasons, but in this case happens to produce a similar result.