2010-02-04 10 views
20

Ich habe zwei Klassen A und B mit einer Viele-zu-Eins-Beziehung von A nach B (mehrere A-Objekte können auf dasselbe B verweisen). Die Frage ist, wenn die Löschregel auf der A-Seite Cascade ist, wird B nur gelöscht, wenn die letzte referenzierende A gelöscht wird oder wird gelöscht die erste Zeit eine assoziierte A wird gelöscht. Die Löschregel für die B-Seite der Beziehung lautet Nulify, wenn dies von Bedeutung ist.iPhone Core Data: Kaskadierendes Löschen über eine Viele-zu-Eins-Beziehung

Außerdem habe ich in den Core Data-Dokumenten gelesen, dass das optionale Flag in einigen Fällen wichtig ist. Aber es war nicht klar, wie sich die Beziehungen, die sie illustrierten, auf meinen Fall bezogen. Sie sprachen über einen Eindämmungsfall (B gehört A), während mein Fall eine der Subskriptionen/Assoziationen ist (B ist verwandt mit A).

Ich konnte einfach programmgesteuert im Code löschen, wollte aber Core Data das richtige tun, wenn möglich. Aber es ist nicht klar, dass die gesuchte Garbage-Collection-Semantik in Core Data unterstützt wird.

Irgendwelche Vorschläge?

Antwort

14

hatte ich das gleiche Ziel wie Sie offenbar hatte (B, sobald die A gelöscht wird verwiesen zuletzt löschen). Ich brauchte länger als erwartet, um das richtig zu machen. Vor allem, weil

  • Zu der Zeit A zum Löschen möglicherweise nicht noch aktualisiert, die zu-viele-Beziehung in B vorbereitet, so dass Sie nicht nur die A in B verwiesen zählen können.
  • isDeleted auf A scheint bereits während -prepareForDeletion

Hier ist, was für mich gearbeitet gesetzt werden, wenn jemand interessiert (I Abteilung < verwenden werden - >>Mitarbeiter, weil es leichter zu lesen):

In Mitarbeiter:

- (void)prepareForDeletion { 
    // Delete our department if we we're the last employee associated with it. 
    Department *department = self.department; 
    if (department && (department.isDeleted == NO)) { 
     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isDeleted == NO"]; 
     NSSet *employees = [department.employees filteredSetUsingPredicate:predicate]; 

     if ([employees count] == 0) {   
      [self.managedObjectContext deleteObject:department]; 
     } 
    } 
} 

Andere Leute haben vorgeschlagen, diese Logik in -willSave in Abteilung zu setzen. Ich bevorzuge die obige Lösung, da ich in einigen Fällen tatsächlich eine leere Abteilung speichern möchte (z. B. während der manuellen Ladenmigration oder des Datenimports).

+0

Nur ein Vorschlag ... Da die docs Nachricht Super nicht sagen, dass es nicht notwendig ist, ist es wahrscheinlich eine gute Idee zu tun also: [super prepareForDeletion] –

0

Hier ist eine Swift 4 Version von Lukas' Antwort:

public override func prepareForDeletion() { 
    guard let department = department else { return } 

    if department.employees.filter({ !$0.isDeleted }).isEmpty { 
     managedObjectContext?.delete(department) 
    } 
}