Atributos exclusivos de dados principais

É possível tornar um atributo Core Data único, ou seja, não há dois objects MyEntity que possam ter o mesmo myAttribute?

Eu sei como aplicar isso de forma programática, mas eu espero que haja uma maneira de fazer isso usando o editor gráfico de modelos de dados no xcode.

Estou usando o SDK do iPhone 3.1.2.

Toda vez que eu crio em object, executo um método de class que faz uma nova Entidade apenas quando outra não existe.

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

Decidi usar o método validate:error: para verificar se já existe um object gerenciado com o valor específico de . Um erro é levantado se este for o caso.

Por exemplo:

  - (BOOL) validateMyAttribute: (id *) erro de valor: erro (NSError **) {
     // Retorna NO se já existe um object com um myAtribute de valor
 } 

Obrigado a Martin Cote por sua contribuição.

A partir do IOS 9, há uma nova maneira de lidar com restrições exclusivas.

Você define os atributos exclusivos no modelo de dados.

Você precisa definir uma diretiva de mesclagem de contexto gerenciada “Mesclar objects singleton de diretiva que definem formas padrão de lidar com conflitos durante uma operação de salvamento” NSErrorMergePolicy é o padrão. Essa diretiva faz com que um salvamento falhe se houver algum conflito de mesclagem.

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

As várias opções são discutidas na Política de mesclagem da Apple Ducumentation

É respondido bem aqui Zachary Orr’s Answer

e ele também gentilmente criou um post de blog e um exemplo de código.

Código de amostra

Postagem do blog

A parte mais desafiadora é obter os atributos do Modelo de dados editáveis. O Segredo é clicar com o botão esquerdo do mouse e, em seguida, clicar com o botão direito, depois de clicar no sinal de + para adicionar uma restrição.

insira a descrição da imagem aqui

Você pode replace o método setMyAttribute (usando categorias) e garantir a exclusividade, embora isso possa ser caro:

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

Se você quiser ter certeza de que cada instância MyEntity tenha um valor myAttribute distinto, você pode usar o objectID dos objects NSManagedObject para esse assunto.

Eu realmente gostei da abordagem @DoozMen !! Eu acho que é a maneira mais fácil de fazer o que eu precisava fazer.

Foi assim que eu coloquei no meu projeto:

O código a seguir circula ao desenhar um tableView bastante longo, salvando no DB um object para cada linha da tabela e definindo vários atributos de object para cada um, como estados UISwitch e outras coisas: se o object para a linha com uma determinada tag não estiver presente dentro do DB, ele cria.

 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; 

Dê uma olhada na documentação da Apple para validação entre propriedades. Ele descreve como você pode validar uma operação específica de inserção ou atualização enquanto pode consultar o database inteiro.