Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent Core Data making duplicates in iOS 5?

I've run into a problem.

Over the weekend I've been working on a project where I'm pulling a large xml from a webservice.

It basically has 3 tiers - Clients, Managers, Staff all hierarchical. So the first time the app runs, it pulls this xml and parses it and creates all the entries in the 3 releated Entities - Clients, Managers and Staff.

Every time the app launches I need to pull that same XML down, but this time, I only need to 'update' any of the existing records that have changed, or add new ones for new clients, managers or staff that have appeared since last time.

So - at the moment, as I said, it's pulling it all, parsing it correctly and creating the correct entities and filling in all the attributes.

However, with no data change, on the 2nd launch it's DUPLICATING all of the data - so instead of 15 clients ( the correct number ) I have 30 and so on...

Do I really have to add lots of code in my parsing to check that instead of creating a new NSManagedObject, I check if it's already there?

And if it is - I have to then manually check every attribute?

That's awfully painful and longwinded - isn't there a way to make Core Data do this kinda stuff for me - automatically?

Thanks for any help or suggestions.

like image 876
iOSProgrammingIsFun Avatar asked Mar 11 '12 15:03

iOSProgrammingIsFun


People also ask

How do you make a core data attribute unique with constraints?

If you look in the Data Model inspector you'll see a field marked "Constraints" – click the + button at the bottom of that field. A new row will appear saying "comma,separated,properties". Click on that, hit Enter to make it editable, then type "sha" and hit Enter again. Make sure you press Cmd+S to save your changes!

Should I use Core Data iOS?

The next time you need to store data, you should have a better idea of your options. Core Data is unnecessary for random pieces of unrelated data, but it's a perfect fit for a large, relational data set. The defaults system is ideal for small, random pieces of unrelated data, such as settings or the user's preferences.

What is core data on iPhone?

Core Data is a framework that you use to manage the model layer objects in your application. It provides generalized and automated solutions to common tasks associated with object life cycle and object graph management, including persistence.


2 Answers

I fear you have to keep your DB clean by yourself … The easiest way would be using NSFetchRequest: When importing your updated data you can run a query against the existing data and decide what you want to do.

As Marcus S. Zarra mentioned in another thread about this topic:

When you are importing a new row you can run a query against the existing rows to see if it is already in place. To do this you create a NSFetchRequest against your entity, set the predicate to look for the guid property and set the max rows returned to 1.

I would recommend keeping this NSFetchRequest around during your import so that you can reuse it while going through the import. If the NSFetchRequest returns a row you can update that row. If it does not return a row then you can insert a new row.

When done correctly you will find the performance more than acceptable.

Another source for good information are Apples Programming Guides: Core Data Programming Guide

like image 79
dom Avatar answered Oct 19 '22 23:10

dom


As Stated in Apple Docs https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html

You need to loop the data model and handle it from there like this

Example:

// loop over employeeIDs
// anID = ... each employeeID in turn
// within body of loop

NSString *predicateString = [NSString stringWithFormat: @"employeeID == %@", anID];

NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];

Personally I do not like this method and I wrote this snippet of code that handles this in a pro-efficient manor and which is straight forward! I noticed with Apples method I ran into issues with strings having different characters such as capitol letters and spaces. Below code is tested and working if you rename all your corresponding objects correctly I honestly believe this is the most efficient way to accomplish not adding duplicates in core data.

-(void)AvoidDuplicatesinDataModel
{
    // Define our table/entity to use
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Users"
                                              inManagedObjectContext:managedObjectContext];

    // Setup the fetch request
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entity];

    // Define how we will sort the records
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"users"
                                                                   ascending:NO];
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];

    [request setSortDescriptors:sortDescriptors];
    [sortDescriptor release];

    // Fetch the records and handle an error
    NSError *Fetcherror;
    NSMutableArray *mutableFetchResults = [[managedObjectContext
                                            executeFetchRequest:request error:&Fetcherror] mutableCopy];

    if (!mutableFetchResults) {
        // Handle the error.
        // This is a serious error
    }

    //here usersNameTextField.text can be any (id) string that you are searching for
    if ([[mutableFetchResults valueForKey:@"users"]
         containsObject:usernameTextField.text]) {
        //Alert user or handle your duplicate methods from here
        return;
    }
}
like image 31
FreeAppl3 Avatar answered Oct 20 '22 00:10

FreeAppl3