CoreData: awakeFromInsert in Bezug auf "Relationship"?

  • CoreData: awakeFromInsert in Bezug auf "Relationship"?

    Ich habe eine Core-Data-App (nicht Document-based). Für die Entity "Wort" habe ich einen Array-Controller "woerter". Wenn ich ein neues Objekt "Wort" erstelle, dann füge ich mit der "awakeFromInsert"-Methode den verschiedenen Attributen neue Standardwerte hinzu. Neben einigen Attributen hat die Entity "Wort" aber auch eine Relationship "thema" (Verbindung zu einer anderen Entity "Thema"). Der Wert in "thema" lässt sich aber durch die awakeFromInsert-Methode nicht verändern, zumindest nicht so wie bei den restlichen Attributen:

    Quellcode

    1. [self setValue:@"NeuesThema" forKey:@"thema"];

    Wieso funktioniert das nicht bzw. was muss ich anders machen, damit ich dem neuen Objekt ein neues Thema verpassen kann?
    XcodeScout
  • Eine Beziehung ist nicht vom Typ NSString.
    Ist mit jedem Wort genau ein Thema zu assoziieren oder mehrere? Falls genau eines:

    Du erzeugst mit Hilfe der NSEntityDescription ein neues Thema-Objekt und setzt das dann mit setValue:forKey: als Thema des Wortes.

    Hast du eine to-many Beziehung musst du das erzeugte Thema-Objekt zunächst in ein NSSet packen +setWithObject: und dies dann mit setValue:forKey: zum "Thema" des Wortes machen.
    Die Objective-Cloud ist fertig wenn sie fertig ist. Beta heißt Beta.

    Objective-C und Cocoa Band 2: Fortgeschrittene
    Cocoa/Objective-C Seminare von [co coa:ding].
  • @Objcler: ja, mit jedem Wort ist genau ein Thema zu assoziieren. Habe gemäss Deiner Beschreibung folgendes gemacht:

    Quellcode

    1. NSManagedObjectContext* context;
    2. NSEntityDescription* entity;
    3. id appDelegate = [[NSApplication sharedApplication] delegate];
    4. context = [appDelegate managedObjectContext];
    5. entity = [NSEntityDescription entityForName:@"Thema"
    6. inManagedObjectContext:context];
    7. [entity setValue: @"NeuesThema" forKey:@"themaName"];
    8. [self setValue:entity forKey:@"thema"];
    "themaName" ist ein Attribut des Entity "Thema". Leider hat dies nicht funktioniert. Fehlermeldung:

    [<NSEntityDescription 0x175250> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key themaName.
    XcodeScout
  • @Objcler: ja, jetzt hat es bereits zur Hälfte geklappt. Die Relationship "thema" wird nun wie erhofft im Entity "Wort" gesetzt. Allerdings wird nun in der Entity "Thema" jedesmal ein Neues Thema erstellt, auch wenn ein bestimmtes Thema bereits vorhanden ist. Wie kann man das hinzufügen von bereits vorhandenen Themen verhindern? Hier ist mein Code:

    Quellcode

    1. NSManagedObject *newObject = [[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:context] autorelease];
    2. [newObject setValue: @"NeuesThema" forKey:@"themaName"];
    3. [self setValue:newObject forKey:@"thema"];
    XcodeScout
  • Nehmen wir an, mein Entity "Thema" besteht im Moment aus drei Objekten "Abenteuer", "Action" und "Drama". Wenn ich nun ein neues "Wort"-Objekt erstelle und dabei die Relationship "thema" so setze, wie von Dir vorgeschlagen, dann wird jedesmal ein neues Themen-Objekt erzeugt, auch wenn ich ein bereits bestehendes Thema benutze.

    Mit anderen Worten, wenn ich dem Neuen Wort-Objekt das Thema "Abenteuer" zuweise, dann wird gleichzeitig auch ein viertes Thema-Objekt erzeugt: nun habe ich also: "Abenteuer", "Action", "Drama" und "Abenteuer. Ich möchte aber, dass meiner Themen-Liste nicht ein neues Objekt hinzugefügt wird, wenn es bereits vorhanden ist.
    XcodeScout
  • Original von XcodeScout
    Nehmen wir an, mein Entity "Thema" besteht im Moment aus drei Objekten "Abenteuer", "Action" und "Drama". Wenn ich nun ein neues "Wort"-Objekt erstelle und dabei die Relationship "thema" so setze, wie von Dir vorgeschlagen, dann wird jedesmal ein neues Themen-Objekt erzeugt, auch wenn ich ein bereits bestehendes Thema benutze.

    Mit anderen Worten, wenn ich dem Neuen Wort-Objekt das Thema "Abenteuer" zuweise, dann wird gleichzeitig auch ein viertes Thema-Objekt erzeugt: nun habe ich also: "Abenteuer", "Action", "Drama" und "Abenteuer. Ich möchte aber, dass meiner Themen-Liste nicht ein neues Objekt hinzugefügt wird, wenn es bereits vorhanden ist.


    Willst du nicht lieber das Thema eines Wortes standardmäsig leer lassen und den User explizit eines angeben lassen? Wenn du dir bei der Erzeugung eines neuen Wortes mehr oder weniger wahllos ein Thema suchst und dem neuen Wort zuweist ist das ja wohl nicht im Sinne des Users. Falls du es dennoch machen möchtest:

    Mit NSFetchRequest kannst du alle vorhandenen Themen ermitteln, dir eines aussuchen und dann dem Wort zuweisen.
    Die Objective-Cloud ist fertig wenn sie fertig ist. Beta heißt Beta.

    Objective-C und Cocoa Band 2: Fortgeschrittene
    Cocoa/Objective-C Seminare von [co coa:ding].
  • Original von Objcler Willst du nicht lieber das Thema eines Wortes standardmäsig leer lassen und den User explizit eines angeben lassen?

    Nein, ich möchte ganz Bewusst am Anfang einen Standardwert setzen. Mit dem NSFetchRequest hat es funktioniert. Wenn ich nun mit Add: ein neues Wort einfüge, dann wird das Thema richtig gesetzt. Allerdings erscheinen nun in der "Woerter"-Tabelle komischerweise immer gleich zwei neue (gleiche) Einträge auf einmal. Wieso ?!? Wenn ich das Programm beende und nochmals neu starte, dann stimmt die Anzahl wieder (d.h. es wurde tatsächlich nur ein Eintrag eingefügt). Aber wieso wird das neue Wort nach dem Einfügen zuerst doppelt angezeigt? Hier mein Code:

    Quellcode

    1. entity = [NSEntityDescription entityForName:@"Thema" inManagedObjectContext:context];
    2. predicate = [NSPredicate predicateWithFormat:@"themaName == 'Thema'"];
    3. fetch = [[[NSFetchRequest alloc] init] autorelease];
    4. [fetch setEntity:entity];
    5. [fetch setPredicate:predicate];
    6. result = [context executeFetchRequest:fetch error:&error];
    7. [self setValue:[result objectAtIndex:0] forKey:@"thema"];
    XcodeScout
  • Original von XcodeScout
    Original von Objcler Willst du nicht lieber das Thema eines Wortes standardmäsig leer lassen und den User explizit eines angeben lassen?

    Nein, ich möchte ganz Bewusst am Anfang einen Standardwert setzen. Mit dem NSFetchRequest hat es funktioniert. Wenn ich nun mit Add: ein neues Wort einfüge, dann wird das Thema richtig gesetzt. Allerdings erscheinen nun in der "Woerter"-Tabelle komischerweise immer gleich zwei neue (gleiche) Einträge auf einmal. Wieso ?!? Wenn ich das Programm beende und nochmals neu starte, dann stimmt die Anzahl wieder (d.h. es wurde tatsächlich nur ein Eintrag eingefügt). Aber wieso wird das neue Wort nach dem Einfügen zuerst doppelt angezeigt? Hier mein Code:

    Quellcode

    1. entity = [NSEntityDescription entityForName:@"Thema" inManagedObjectContext:context];
    2. predicate = [NSPredicate predicateWithFormat:@"themaName == 'Thema'"];
    3. fetch = [[[NSFetchRequest alloc] init] autorelease];
    4. [fetch setEntity:entity];
    5. [fetch setPredicate:predicate];
    6. result = [context executeFetchRequest:fetch error:&error];
    7. [self setValue:[result objectAtIndex:0] forKey:@"thema"];


    Ahh. Ja. Ich glaube man darf in awakeFromInsert kein fetchRequest schicken. Habe mal bei cocoadev sowas gelesen. Du rufst aber schon super auf - oder?
    Die Objective-Cloud ist fertig wenn sie fertig ist. Beta heißt Beta.

    Objective-C und Cocoa Band 2: Fortgeschrittene
    Cocoa/Objective-C Seminare von [co coa:ding].
  • Ich würde die Logik in einen eigenen Controller packen. Dem Controller kannst du ein Outlet auf einen Wort-ArrayController und ein Outlet auf einen Thema-ArrayController spendieren. Dein Controller kann ein neues Wort anlegen und den Thema-ArrayController um ein Thema bitten.

    Denke daran: Fetches sind recht teure Operationen. Außerdem gehört der Prozess des Anlegens eines neuen Themas eher in die Controller als in die Modelschicht.
    Die Objective-Cloud ist fertig wenn sie fertig ist. Beta heißt Beta.

    Objective-C und Cocoa Band 2: Fortgeschrittene
    Cocoa/Objective-C Seminare von [co coa:ding].