2012-12-27 4 views
9

Die meisten (alles, was ich gesehen habe) Core Data Tutorials verwenden Sie den folgenden Code-Schnipsel mit @"MyEntityClass" hartcodiert in:Generiert NSStringFromClass ([MyEntityClass-Klasse]) einen sicheren Core Data Entity-Namen?

NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"MyEntityClass"]; 

Ist es sicher NSStringFromClass() als Entity-Namen zu verwenden?

NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:NSStringFromClass([MyEntityClass class])]; 

Diese Nähte viel einleuchtender zu sein mit Bezug auf Refactoring und dergleichen zu behandeln. Zumal ich Xcode habe, um meine Unterklassen zu erstellen. Ich frage, weil ich das noch nie zuvor gesehen habe, also vermisse ich vielleicht etwas.

Antwort

14

Ja, dieser Code ist in Ordnung, Wenn die Klasse Ihrer Entität in Ihrem Modell auf MyEntityClass festgelegt ist.

Ich ziehe die Entity-Klasse eine Klassenmethode geben, die das Unternehmen Namen zurückgibt:

+ (NSString *)entityName { 
    return NSStringFromClass(self); 
} 

und es so nennen:

NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:[MyEntityClass entityName]]; 

diese Weise, wenn ich die Klasse ändern wollen nennen, ohne den Entity-Namen in dem Modell zu ändern, kann ich nur die Änderung der Klassenmethode:

+ (NSString *)entityName { 
    return @"NewEntityName"; 
} 

Warum sollte ich das tun? Nun, ich könnte mich für einen besseren Namen für die Entität entscheiden. Durch das Ändern des Klassennamens wird die Kompatibilität mit einem vorhandenen permanenten Stammdatenspeicher nicht aufgehoben, aber der Entitätsname in der Modelldatei wird geändert. Ich kann den Klassennamen und die entityName Methode ändern, aber den Entitätsnamen im Modell unverändert lassen, und dann muss ich mich nicht um die Migration kümmern. (Lightweight migration unterstützt umbenannte Entitäten, so dass es nicht so groß ist.)

Sie könnten weiter gehen und haben tatsächlich die entityName Methode suchen den Entitätsnamen aus dem verwalteten Objektmodell zur Laufzeit. Angenommen, Ihre Anwendung Delegierte hat eine Nachricht, dass das verwaltete Objektmodell zurückgibt:

+ (NSString *)entityName { 
    static NSString *name; 
    static dispatch_once_t once; 
    dispatch_once(&once, ^{ 
     NSString *myName = NSStringFromClass(self); 
     NSManagedObjectModel *model = [(AppDelegate *)[UIApplication delegate] managedObjectModel]; 
     for (NSEntityDescription *description in model.entities) { 
      if ([description.managedObjectClassName isEqualToString:myName]) { 
       name = description.name; 
       break; 
      } 
     } 
     [NSException raise:NSInvalidArgumentException 
      format:@"no entity found that uses %@ as its class", myName]; 
    }); 
    return name; 
} 

Natürlich, wenn Sie wirklich tun wollen, sollten Sie den Inhalt des dispatch_once Block in eine Hilfsmethode ausklammern, wahrscheinlich auf Ihrer App delegieren (oder wo auch immer Sie das Modell bekommen).

+0

Wenn Sie nicht so weit gehen möchten, den zusätzlichen Lookup-Code hinzuzufügen, können Sie diese Assert vor jedem internen Zugriff auf 'entityName: 'hinzufügen. 'NSAssert (context.persistentStoreCoordinator.managedObjectModel.entitiesByName [[self entityName]]! = Nil, @" Entität mit dem Namen% @ nicht im Modell gefunden. Ist Ihr Klassenname identisch mit Ihrem Entitätsnamen? ", [Self entityName ]); 'Dadurch erhalten Sie zur Laufzeit einen Fehler, wenn der Entitätsname Ihres Modells nicht mit dem Namen Ihrer Klasse übereinstimmt. –

+0

In diesem Fall müssen Sie der Kategorie jedes automatisch generierten Objekts Code hinzufügen? nur besorgt, neue Datei für Klassen zu erstellen, um nur diese Funktion hinzuzufügen. –

+0

@VitaliK Sie könnten 'NSManagedObject' eine Kategorie hinzufügen, aber wenn Sie dies tun, nennen Sie es nicht 'entityName', da dies zu allgemein ist. Verwenden Sie ein Präfix wie 'Vitali_entityName', um Namenskollisionen zu vermeiden. –