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:
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 sameid
, Core Data will use the merge policy to make sure you don't get a duplicateid
.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.