Search code examples
iphoneioscore-datapreload

Updating preloaded data alongside user-data in a Core Data app


Simple problem, but for me, tough execution. I'm working solely on an app that is in alpha, but my testers need to have the most up-to-date database. I have a Core Data model with two entities: Clothing and ClothingRecord.

Clothing is a "static" model that has preloaded data (things like Hat, Shirt, Pants, etc) that will only change whenever I update the model.

ClothingRecord is user populated entity that has relationships with entity Clothing.

enter image description here

What I've just run into is that I want to change the data in Clothing. Not only change properties of Clothing (like change name from "Hat" to "Cap"), but I want to add and remove items as well.

I'm fairly new to Core Data so I used Ray Wenderlich's tutorial on how to preload data: http://www.raywenderlich.com/980/core-data-tutorial-how-to-preloadimport-existing-data

This worked great for the first time. I have a database up and running. Now, however, that I've changed it, I'm not sure how to properly update the Clothing entity. Do I traverse all objects and compare? Do I just add new things? I can't go and delete objects because of existing relationships, right?

Are there guides or tutorials on how to update a Core Data driven app with preloaded data? I would imagine that this is happens all of the time, but I can't find any solid resources on it.


Solution

  • Do I traverse all objects and compare? Do I just add new things? I can't go and delete objects because of existing relationships, right?

    It depends. I'll try to give you some suggestions.

    Do I traverse all objects and compare?

    To traverse and compare, first, I will insert an attribute that works as an identifier (e.g. guid). Having an identifier could let you to compare objects that you retrieve with Core Data. For example if "Hat" has a guid with 1234 and "Cap" has the same guid, you could simply fetch through the identifier and update that object with the new name. This is can be achieved by setting up a NSPredicate (how-to-update-existing-object-in-core-data).

    Do I just add new things?

    You can do it if you have no relationships with the second entity. On contrary you need to link the new object with the original relationships.

    I can't go and delete objects because of existing relationships

    The same as before, you need to ricreate those relationships and then delete the objects you are interested in.

    I will try the first solution, if you have just started with CD. I also suggest an old answer that I wrote in a previous SO post about Core Data in general (mapping-business-objects-with-core-data-in-ios).

    Hope it helps.

    Edit

    About the last two options, you could perform a two steps operation.

    First, create a request that let you to grab the pre-populated Clothing objects.

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:[NSEntityDescription entityForName:@"Clothing" inManagedObjectContext:moc]];
    
    NSError *error = nil;
    NSArray *results = [moc executeFetchRequest:request error:&error];
    

    The array results contains the objects retrieved, now with a for-loop create new object and set right relationships.

    for(Clothing* clothing in results) {
    
        Clothing* newClothing = [NSEntityDescription insertNewObjectForEntityForName:@"Clothing" inManagedObjectContext:moc];
        newClothing.name = @"Cap";
        newClothing.relationshipToWhatYouWant = clothing.relationshipToWhatYouWant;
    }
    

    Finally, if you want, remove the old objects.

    P.S. Check the code because I've written by hand.