Как предотвратить дублирование Core Data в iOS 5? - PullRequest
9 голосов
/ 11 марта 2012

Я столкнулся с проблемой.

На выходных я работал над проектом, в котором я извлекаю большой XML-файл из веб-службы.

В основном он имеет 3ярусы - клиенты, менеджеры, персонал весь иерархический.Поэтому при первом запуске приложения оно извлекает этот XML-файл, анализирует его и создает все записи в трех опубликованных сущностях - клиенты, менеджеры и персонал.

Каждый раз, когда приложение запускается, мне нужно извлечь тот же самый XMLвниз, но на этот раз мне нужно только «обновить» любые существующие записи, которые изменились, или добавить новые для новых клиентов, менеджеров или сотрудников, которые появились с прошлого раза.

Итак - намомент, как я уже сказал, он тянет все это, правильно анализирует и создает правильные сущности и заполняет все атрибуты.

Однако, без изменения данных, при 2-м запуске происходит ДУБЛИРОВАНИЕ всех данныхпоэтому вместо 15 клиентов (правильное число) у меня есть 30 и так далее ...

Действительно ли мне нужно добавлять много кода в мой анализ, чтобы проверить, что вместо создания нового NSManagedObject я проверяю,это уже там?

А если это так - мне нужно вручную проверять каждый атрибут?

Это ужасно больно и затянуто - не так ли?Есть ли способ заставить Core Data делать такие вещи для меня - автоматически?

Спасибо за любую помощь или предложения.

Ответы [ 2 ]

12 голосов
/ 11 марта 2012

Боюсь, что вы должны содержать свою БД в чистоте самостоятельно ... Самый простой способ - использовать NSFetchRequest: при импорте обновленных данных вы можете выполнить запрос к существующим данным и решить, что вы хотите сделать.

Как отметил Маркус С. Зарра в другой теме об этой теме:

Когда вы импортируете новую строку, вы можете выполнить запрос к существующим строкам, чтобы увидеть,это уже на месте.Для этого вы создаете NSFetchRequest для вашей сущности, устанавливаете предикат для поиска свойства guid и устанавливаете максимальное количество возвращаемых строк равным 1.

Я бы порекомендовал сохранить этот NSFetchRequest во время импорта, чтобы вы могли использовать его повторноэто при прохождении импорта.Если NSFetchRequest возвращает строку, вы можете обновить эту строку.Если он не возвращает строку, то вы можете вставить новую строку.

Если все сделано правильно, вы найдете производительность более приемлемой.

Другим источником полезной информации является программирование яблок.Руководства: Руководство по программированию основных данных

3 голосов
/ 27 апреля 2012

Как указано в Apple Docs https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html

Вам нужно зациклить модель данных и обработать ее оттуда вот так

Пример:

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

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

NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];

Лично яМне не нравится этот метод, и я написал этот фрагмент кода, который обрабатывает это в про-эффективном поместье и который прямо вперед!Я заметил, что с помощью метода «Яблоки» я столкнулся с проблемами со строками, имеющими разные символы, такие как буквы заглавной буквы и пробелы.Приведенный ниже код протестирован и работает, если вы правильно переименуете все соответствующие объекты. Я искренне верю, что это наиболее эффективный способ не добавлять дубликаты в основные данные.

-(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;
    }
}
...