2012-01-17 7 views
7

Tengo una entidad en Core Data que tiene un atributo que debe ser único. No hay forma de configurar esto en la interfaz visual. Supongo que necesito crear una clase personalizada que herede de NSManagedObject y luego escribir mi propio método de validación.¿Cómo realizo una validación personalizada (por singularidad) en Datos centrales?

Creé satisfactoriamente la clase personalizada seleccionando las entidades en el editor visual y seleccionando Archivo -> Nuevo -> Nuevo archivo -> subclase NSManagedObject. Lo uso para agregar marcas de tiempo de creación, así sé que funciona.

¿Pero ahora qué? ¿Qué métodos necesito?

El NSManagedObject reference guide me dice que "implemente los métodos de la forma de validar: error:" pero no proporciona un ejemplo.

Preguntas similares here y here, pero necesito un poco más de ayuda.

Un ejemplo completo sería increíble, pero cualquier ayuda es muy apreciada.

+0

¿Intentó alguna de las soluciones en la respuesta que le dieron? Básicamente, verifique la exclusividad antes de llamar a guardar. El código en el segundo ejemplo debería ser todo lo que necesites. – sosborn

+0

@sosborn Los ejemplos solo muestran cómo funciona la validación en sí misma (iterar sobre todos los registros anteriores que buscan el mismo valor), pero no dónde colocarla. –

+0

Simplemente haga un método que devuelva un BOOL. Si es único, devuelva SÍ, de lo contrario, devuelva NO. Llama a ese método Si devuelve SÍ, guarde, si devuelve no, no guarde. – sosborn

Respuesta

2

Esto funciona, aunque es lento en inserciones masivas y aún necesita crear un objeto NSError.

-(BOOL)validateValue:(__autoreleasing id *)value forKey:(NSString *)key error:(NSError *__autoreleasing *)error { 
    [super validateValue:value forKey:key error:error]; 

    // Validate uniqueness of my_unique_id 
    if([key isEqualToString:@"my_unique_id"]) { 
     NSFetchRequest * fetch = [[NSFetchRequest alloc] init]; 
     [fetch setEntity:[NSEntityDescription entityForName:[self.entity name] 
       inManagedObjectContext:self.managedObjectContext]]; 

     NSPredicate *predicate = [NSPredicate 
      predicateWithFormat:@"my_unique_id = %@",[self valueForKey:key]]; 

     fetch.predicate = predicate; 

     NSError *error = nil; 
     NSUInteger count = [self.managedObjectContext 
          countForFetchRequest:fetch error:&error]; 

     if (count > 1) { 
      // Produce error message... 

      // Failed validation: 
      return NO; 
     } 


    } 

    return YES; 
} 
+5

Según Apple [Validación de objetos gestionados] [1], si desea implementar lógica además de las restricciones que proporciona en el modelo de objetos gestionados, no debe anular validateValue: forKey: error :. En su lugar, debe implementar métodos del formulario validar : error :. En su caso, esto es validateMy_unique_id: error: method. [1]: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData/Articles/cdValidation.html –

1

validateValue se mencionan a continuación hará el truco de validación (y el lugar correcto para hacer la validación)

Si utiliza NSFetchedResultsController, sin embargo, no se olvide de quitar objeto de la memoria para evitar objeto duplicado en UITableView incluso en el fracaso Algo como esto:

CustomManagedObject *obj = [NSEntityDescription insertNewObjectForEntityForName:@"<YourEntity>" inManagedObjectContext:self.managedObjectContext]; 
obj.property = @"some property"; 

if (![self.managedObjectContext save:&error]) { 
    [self.managedObjectContext deleteObject:obj]; // delete from memory. Otherwise, you get duplicated value in UITableView even if save has failed 
} 
6

Digamos que usted tiene una propiedad foo que desea validar

De Property-Level Validation:

If you want to implement logic in addition to the constraints you provide in the managed object model, you should not override validateValue:forKey:error: . Instead you should implement methods of the form validate<Key>:error: .

Dónde <Key> es su propiedad. De hecho, implementaría algo como:

-(BOOL)validateFoo:(id *)ioValue error:(NSError **)outError { 
    return [self isUnique]; 
} 
+0

[auto isUnique] no existe, – Necronet

+3

Tiene razón, haría isUnique sea ​​su propio método para determinar la singularidad. – quellish

Cuestiones relacionadas