I'm working with Core Data and the iTunesLibrary framework in a macOS application. During startup, I import information (on my iTunes tracks) from iTunesLibrary.
Media-items in iTunes have unique identifiers (namely the persistentId
on class ITLibMediaItem
) so in my Core-Data store I use this information as a unique attribute on the Song
entity, that represents an iTunes track in my model.
I've marked this attribute (called iTunesID
on my Song
entity) as unique, using Xcode, and I have verified that the constraint is also present, when viewing the raw XML (given in the .xcdatamodel-file) in a text-editor.
If I run my program twice (leading it to import the same data twice), no errors occur on save, and I later verify that the number of elements in the store has doubled. Let me point out, that what I want is to prevent having objects in my store, that represents identical information.
However, I then tested further and had my program try to save two objects (with the same information in them, and specifically identical iTunesID
s) into my context during startup, and here Core-Data does throw an error, saying a uniqueness constraint was violated.
Main-Question
It seems that Core-Data respects uniqueness constraints among objects about to be inserted, while it does not respect uniqueness constraints among an object that is about to be inserted and one that is already in the store...Is this understanding correct?
Btw, I'm using the default merge policy (errorMergePolicyType
) on my NSManagedObjectContext
instance.
Additional question
I'm using a String-representation of the iTunesPersistentID, since I read here, that uniqueness constraints only work on String-attributes in Core-Data; can someone reject/confirm this?
// This leads to the number of elements in my store growing, each time I run my program
for song in songsFromiTunes
{
// Create and insert a managed object into context
let managedObject = NSEntityDescription.insertNewObject(forEntityName: "Song", into: managedObjectContext) as! Song
if let artistName = song.artist?.name
{
managedObject.artist = artistName
}
managedObject.title = song.title
let iTunesIdentifier = "\(song.persistentID.int64Value)"
managedObject.iTunesID = iTunesIdentifier
if let title = song.album.title
{
managedObject.album = title
}
}
Inserting an entity with the same iTunesID
twice, leading the subsequent save()
on managedObjectContext
to throw an error
for _ in 0...1
{
let managedObject = NSEntityDescription.insertNewObject(forEntityName: "Song", into: managedObjectContext) as! Song
managedObject.artist = "Someone"
managedObject.title = "Title"
managedObject.iTunesID = "A String"
managedObject.album = "AlbumTitle"