2012-01-17 19 views
7

Mam jednostkę w danych podstawowych, która ma atrybut, który musi być unikalny. Nie można tego ustawić w interfejsie graficznym. Zakładam, że muszę utworzyć niestandardową klasę dziedziczącą po obiekcie NSManagedObject, a następnie napisać własną metodę sprawdzania poprawności.Jak utworzyć niestandardową weryfikację (dla unikalności) w danych podstawowych?

Pomyślnie utworzyłem klasę niestandardową, wybierając elementy w edytorze wizualnym i wybierając opcję Plik -> Nowy -> Nowy plik -> Podklasa NSManagedObject. Używam tego do dodawania znaczników czasu tworzenia, więc wiem, że to działa.

Ale co teraz? Jakie metody są potrzebne?

The NSManagedObject reference guide mówi mi, aby "wdrożyć metody sprawdzania poprawności formularza: błąd:", ale nie podaje przykładu.

Podobne pytania here i here, ale potrzebuję trochę więcej pomocy.

Kompletny przykład byłby świetny, ale każda pomoc jest doceniana.

+0

Czy wypróbowałeś jedno z rozwiązań w odpowiedzi, którą ci dali? Zasadniczo sprawdź unikalność przed wywołaniem zapisu. Kod w drugim przykładzie powinien być wszystkim, czego potrzebujesz. – sosborn

+0

@sosborn Poniższe przykłady pokazują, jak działa samo sprawdzanie poprawności (iteracja nad wszystkimi poprzednimi rekordami, które szukają tej samej wartości), ale nie w miejscu ich umieszczenia. –

+0

Po prostu wykonaj metodę, która zwraca BOOL. Jeśli jest to unikalny zwrot YES, w przeciwnym razie zwróć NIE. Wezwij tę metodę. Jeśli zwróci TAK, zapisz, jeśli nie zwróci nic, nie rób tego. – sosborn

Odpowiedz

2

To działa, chociaż na insertach masowych działa wolno i nadal trzeba utworzyć obiekt 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

Zgodnie z [Poprawność obiektu zarządzanego obiektu] [1] firmy Apple, jeśli oprócz implementacji ograniczeń w modelu obiektów zarządzanych ma zostać zastosowana logika, nie należy zastępować wartości validateValue: forKey: error :. Zamiast tego należy wdrożyć metody formularza sprawdzania poprawności : błąd :. W twoim przypadku jest to validateMy_unique_id: error: method. [1]: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData/Articles/cdValidation.html –

1

validateValue wymienione poniżej rade walidacji (i prawidłowe miejsce, aby walidacja)

Jeśli używasz NSFetchedResultsController jednak, nie zapomnij, aby usunąć obiekt z pamięci, aby uniknąć powielania obiektu w UITableView nawet w przypadku awarii. coś takiego:

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

Powiedzmy masz nieruchomość foo, który chcesz zweryfikować

Od 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: .

Gdzie <Key> ma swoją nieruchomość. W rzeczywistości możesz zaimplementować coś takiego:

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

[self isUnique] nie istnieje, – Necronet

+3

Jesteś poprawne, by isUnique być własną metodą określania wyjątkowości. – quellish

Powiązane problemy