Подтвердить что ты не робот

Уникальные атрибуты Core Data

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

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

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

4b9b3361

Ответ 1

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

Например:

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

Спасибо Мартину Котту за его вклад.

Ответ 2

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

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

Ответ 3

Из 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

Здесь хорошо сказано Захари Орр Отвечать

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

Пример кода

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

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

введите описание изображения здесь

Ответ 4

Вы можете переопределить метод 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.

Ответ 5

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

Именно так я включил его в свой проект:

Следующие циклы кода при рисовании довольно длинного tableView, сохранение в DB объекта для каждой строки таблицы и установка различных атрибутов объекта для каждого из них, например состояния 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;

Ответ 6

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