Frage

Ich versuche, eine iPhone-Anwendung zu erstellen, wo der Benutzer Einträge hinzufügen kann. Als er einen neuen Eintrag drückt, wird Popup eine Box ihn für einige Informationen zu fragen. Dann kann er entweder die Taste „Cancel“ oder „Speichern“, um die Daten zu verwerfen oder speichern sie auf der Festplatte.

Zum Speichern, ich die Core Data Framework bin mit, was ziemlich gut funktioniert. Allerdings kann ich die Schaltfläche „Abbrechen“, um Arbeit nicht. Wenn das Fenster erscheint, nach Informationen zu fragen, ich ein neues Objekt in dem verwalteten Objektkontext (MOC) erstellen. Dann, wenn der Benutzer drückt abbrechen, ich versuche, die NSUndoManager zum MOC gehören, zu verwenden.

Ich möchte auch es mit verschachtelten Undo-Gruppen zu tun, denn es könnte verschachtelte Gruppen sein.

Um dies zu testen, schrieb ich eine einfache Anwendung. Die Anwendung ist nur die „Window-basierte Anwendung“ Vorlage mit Core Data aktiviert. Für das Core Data-Modell, erstelle ich eine einzige Einheit „Entity“ mit Integer-Attribute „x“ bezeichnet. Dann in der applicationDidFinishLaunching, füge ich diesen Code ein:

- (void)applicationDidFinishLaunching:(UIApplication *)application {    

  // Override point for customization after app launch    

  unsigned int x=arc4random()%1000;
  [self.managedObjectContext processPendingChanges];
  [self.managedObjectContext.undoManager beginUndoGrouping];

  NSManagedObject *entity=[NSEntityDescription insertNewObjectForEntityForName:@"Entity" 
                                                        inManagedObjectContext:self.managedObjectContext];
  [entity setValue:[NSNumber numberWithInt:x] forKey:@"x"];
  NSLog(@"Insert Value %d",x);

  [self.managedObjectContext processPendingChanges];
  [self.managedObjectContext.undoManager endUndoGrouping];
  [self.managedObjectContext.undoManager undoNestedGroup];

  NSFetchRequest *fetchRequest=[[NSFetchRequest alloc] init];
  NSEntityDescription *entityEntity=[NSEntityDescription entityForName:@"Entity"
                                                inManagedObjectContext:self.managedObjectContext];
  [fetchRequest setEntity:entityEntity];
  NSArray *result=[self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
  for(entity in result) {
    NSLog(@"FETCHED ENTITY %d",[[entity valueForKey:@"x"] intValue]);
  }

    [window makeKeyAndVisible];
}

Die Idee ist einfach. Versuchen Sie, ein neues Entity-Objekt einfügen, rückgängig machen es, holen alle Entity-Objekte in der MOC und ausdrucken. Wenn alles richtig funktioniert, sollte es keine Objekte am Ende sein.

Allerdings habe ich diese Ausgabe erhalten:

[Session started at 2010-02-20 13:41:49 -0800.]
2010-02-20 13:41:51.695 Untitledundotes[7373:20b] Insert Value 136
2010-02-20 13:41:51.715 Untitledundotes[7373:20b] FETCHED ENTITY 136

Wie Sie sehen können, ist das Objekt in der MOC, nachdem ich versuche, seine Schöpfung rückgängig zu machen. Irgendwelche Vorschläge, was ich falsch mache?

War es hilfreich?

Lösung

Ihr Problem wird durch die Tatsache verursacht, die, im Gegensatz zu O X, die iPhone Objektkontext verwalten nicht einen Undo-Manager standardmäßig enthalten. Sie müssen explizit hinzufügen.

Ändern Sie den generierten Code in der App Delegat für die managedObjectContext Eigenschaft wie folgt aussehen:

- (NSManagedObjectContext *) managedObjectContext {

    if (managedObjectContext != nil) {
        return managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        managedObjectContext = [[NSManagedObjectContext alloc] init];
        //add the following 3 lines of code
        NSUndoManager *undoManager = [[NSUndoManager alloc] init];
        [managedObjectContext setUndoManager:undoManager];
        [undoManager release];
        [managedObjectContext setPersistentStoreCoordinator: coordinator];
    }

    return managedObjectContext;

}

Nachdem diese Änderung vorgenommen hat, die zweite Protokollmeldung wird nicht mehr gedruckt werden.

Ich hoffe, das hilft ...

Dave

Andere Tipps

habe ich versucht, Dave Ansatz, aber nicht für mich zu arbeiten. Ich fand schließlich die Lösung in Apples Beispiel CoreDataBooks

Der Trick ist, einen neuen Kontext, dass die Aktien der Koordinator mit Ihnen App Kontext zu erstellen. Um die Änderungen zu verwerfen Sie nicht brauchen, etwas zu tun, werfen nur das neue Kontextobjekt. Da Sie den Koordinator teilen, aktualisiert Ihre Haupt Kontext zu speichern.

Hier ist meine angepasste Version, wo ich ein statisches Objekt für den temporären Kontext verwenden, um ein neues ChannelMO Objekt zu erstellen.

//Gets a new ChannelMO that is part of the addingManagedContext
+(ChannelMO*) getNewChannelMO{

    // Create a new managed object context for the new channel -- set its persistent store coordinator to the same as that from the fetched results controller's context.
    NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] init];
    addingManagedObjectContext = addingContext;

    [addingManagedObjectContext setPersistentStoreCoordinator:[[self getContext] persistentStoreCoordinator]];

    ChannelMO* aux = (ChannelMO *)[NSEntityDescription insertNewObjectForEntityForName:@"ChannelMO" inManagedObjectContext:addingManagedObjectContext];
    return aux;
}

+(void) saveAddingContext{
    NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter];
    [dnc addObserver:self selector:@selector(addControllerContextDidSave:) 
                name:NSManagedObjectContextDidSaveNotification object:addingManagedObjectContext];

    NSError *error;
    if (![addingManagedObjectContext save:&error]) {
        // Update to handle the error appropriately.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    }
    [dnc removeObserver:self name:NSManagedObjectContextDidSaveNotification object:addingManagedObjectContext];

    // Release the adding managed object context.
    addingManagedObjectContext = nil;
}

Ich hoffe, es hilft

Gonso

Es sollte funktionieren. Haben Sie richtig die Undo-Manager Ihre managedObjectContext zuweisen? Wenn Sie zu Recht das getan hat, es hat in der Standardeinstellung zurücksetzen Registrierung aktiviert ist, und Sie sollten gut zu gehen. Es gibt einen guten Artikel auf Kerndaten hier . Es ist ein gutes Tutorial auf Kerndaten und NSUndoManager hier . Ich hoffe, das hilft.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top