Уникальные атрибуты базовых данных - PullRequest
35 голосов
/ 10 февраля 2010

Можно ли сделать атрибут Core Data уникальным, то есть два объекта MyEntity не могут иметь одинаковый атрибут myAttribute?

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

Я использую iPhone 3.1.2 SDK.

Ответы [ 6 ]

28 голосов
/ 09 марта 2012

Каждый раз, когда я создаю объект, я выполняю метод класса, который создает новый объект только тогда, когда другой объект не существует.

+ (TZUser *)userWithUniqueUserId:(NSString *)uniqueUserId inManagedObjectContext:(NSManagedObjectContext *)context
{
    TZUser *user = nil;
    NSFetchRequest *request = [[NSFetchRequest alloc] init];

    request.entity = [NSEntityDescription entityForName:@"TZUser" inManagedObjectContext:context];
    request.predicate = [NSPredicate predicateWithFormat:@"objectId = %@", uniqueUserId];
    NSError *executeFetchError = nil;
    user = [[context executeFetchRequest:request error:&executeFetchError] lastObject];

    if (executeFetchError) {
         NSLog(@"[%@, %@] error looking up user with id: %i with error: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), [uniqueUserId intValue], [executeFetchError localizedDescription]);
    } else if (!user) {
        user = [NSEntityDescription insertNewObjectForEntityForName:@"TZUser" 
                                             inManagedObjectContext:context];
    }

    return user;
}
12 голосов
/ 11 февраля 2010

Я решил использовать метод validate<key>:error:, чтобы проверить, существует ли уже управляемый объект с конкретным значением <key>. В этом случае возникает ошибка.

Например:

- (BOOL)validateMyAttribute:(id *)value error:(NSError **)error {
    // Return NO if there is already an object with a myAtribute of value
}

Благодарю Мартина Кота за его вклад.

9 голосов
/ 13 октября 2015

В IOS 9 появился новый способ обработки уникальных ограничений.

Вы определяете уникальные атрибуты в модели данных.

Вам необходимо установить управляемую политику слияния контекста «Объекты политики слияния с одним элементом, определяющие стандартные способы обработки конфликтов во время операции сохранения». NSErrorMergePolicy используется по умолчанию. Эта политика приводит к сбою сохранения при любых конфликтах слияния. *

- (NSManagedObjectContext *)managedObjectContext {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (!coordinator) {
        return nil;
    }
  _managedObjectContext = [[NSManagedObjectContext alloc]    initWithConcurrencyType:NSMainQueueConcurrencyType];
  [_managedObjectContext setPersistentStoreCoordinator:coordinator];
  [_managedObjectContext setMergePolicy:NSOverwriteMergePolicy];
    return _managedObjectContext;
}

Различные варианты обсуждаются в Политика слияния Apple Ducumentation

Здесь хорошо ответили Ответ Захари Орра

и он также любезно создал пост блога и пример кода.

Пример кода

Сообщение в блоге

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

enter image description here

3 голосов
/ 10 февраля 2010

Вы можете переопределить метод setMyAttribute (используя категории) и обеспечить уникальность прямо здесь, хотя это может быть дорого:

- (void)setMyAttribute:(id)value
{
   NSArray *objects = [self fetchObjectsWithMyValueEqualTo:value];
   if( [objects count] > 0 )  // ... throw some exception
   [self setValue:value forKey:@"myAttribute"];
}

Если вы хотите убедиться, что каждый экземпляр MyEntity имеет отдельное значение myAttribute, вы можете использовать objectID из NSManagedObject объектов в этом отношении.

0 голосов
/ 03 августа 2015

Взгляните на документацию Apple для проверки свойств. В нем описывается, как вы можете проверить правильность конкретной операции вставки или обновления, а также просмотреть всю базу данных.

0 голосов
/ 25 июля 2013

Мне очень понравился подход @DoozMen !! Я думаю, что это самый простой способ сделать то, что мне нужно было сделать.

Вот как я встроил его в свой проект:

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

NSFetchRequest *request = [[NSFetchRequest alloc] init];

request.entity = [NSEntityDescription entityForName:@"Obiettivo" inManagedObjectContext:self.managedObjectContext];
request.predicate = [NSPredicate predicateWithFormat:@"obiettivoID = %d", obTag];
NSError *executeFetchError = nil;
results = [[self.managedObjectContext executeFetchRequest:request error:&executeFetchError] lastObject];

if (executeFetchError) {
    NSLog(@"[%@, %@] error looking up for tag: %i with error: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), obTag, [executeFetchError localizedDescription]);
} else if (!results) {

    if (obbCD == nil) {
    NSEntityDescription *ent = [NSEntityDescription entityForName:@"Obiettivo" inManagedObjectContext:self.managedObjectContext];
    obbCD = [[Obiettivo alloc] initWithEntity:ent insertIntoManagedObjectContext:self.managedObjectContext];
    }

    //set the property that has to be unique..
    obbCD.obiettivoID = [NSNumber numberWithUnsignedInt:obTag];

    [self.managedObjectContext insertObject:obbCD];
    NSError *saveError = nil;
    [self.managedObjectContext save:&saveError];

    NSLog(@"added with ID: %@", obbCD.obiettivoID);
    obbCD = nil;
}

results = nil;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...