Question

Je suis en train de créer une application iPhone où l'utilisateur peut ajouter des entrées. Quand il appuie sur une nouvelle entrée, une boîte pour lui demander apparaitre quelques informations. Ensuite, il peut soit appuyer sur « Annuler » ou « Enregistrer » pour supprimer les données ou l'enregistrer sur le disque.

Pour sauver, je suis en utilisant le framework Core Data, qui fonctionne assez bien. Cependant, je ne peux pas obtenir le bouton « Annuler » pour travailler. Lorsque la fenêtre apparaît, demandant des informations, je crée un nouvel objet dans le contexte de l'objet géré (MOC). Ensuite, lorsque l'utilisateur appuie annuler, je tente d'utiliser le NSUndoManager appartenant au MOC.

Je voudrais aussi faire en utilisant des groupes imbriqués undo, car il pourrait être des groupes imbriqués.

Pour tester cela, je l'ai écrit une application simple. L'application est tout simplement le modèle « d'application de la fenêtre » avec Core Data activé. Pour le modèle de base de données, je crée une seule entité appelée « entité » avec l'attribut entier « x ». Puis à l'intérieur du applicationDidFinishLaunching, ajouter ce code:

- (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];
}

L'idée est simple. Essayez d'insérer un nouvel objet de l'entité, défaire, chercher tous les objets d'entité dans le MOC et les imprimer. Si tout fonctionne correctement, il devrait y avoir aucun objet à la fin.

Cependant, je reçois cette sortie:

[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

Comme vous pouvez le voir, l'objet est présent dans le MOC après que j'essaie de défaire sa création. Toutes les suggestions quant à ce que je fais mal?

Était-ce utile?

La solution

Votre problème est causé par le fait que, contrairement à OS X, le contexte d'objet géré iPhone ne contient pas un gestionnaire d'annulation par défaut. Vous devez ajouter explicitement un.

Modifier le code généré dans le délégué de l'application de la propriété managedObjectContext pour ressembler à ceci:

- (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;

}

Après avoir fait ce changement, le 2ème message du journal n'est plus imprimé.

Hope qui aide ...

Dave

Autres conseils

J'ai essayé l'approche Dave, mais ne travaille pas pour moi. J'ai finalement trouvé la solution dans l'exemple d'Apple CoreDataBooks

L'astuce consiste à créer un nouveau contexte qui partage le coordinateur avec vous le contexte App. Pour annuler les modifications que vous ne avez pas besoin de faire une chose, juste jeter le nouvel objet de contexte. Depuis que vous partagez le coordinateur, l'économie met à jour votre contexte principal.

Voici ma version adaptée, où j'utiliser un objet statique pour le contexte temporaire pour créer un nouvel objet ChannelMO.

//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;
}

J'espère que cela aide

Gonso

Il devrait fonctionner. Avez-vous attribué correctement le gestionnaire de undo à votre managedObjectContext? Si vous avez fait à juste titre que, par défaut a annuler l'enregistrement activé, et vous devriez être bon d'aller. Il y a un bon article sur les données de base . Il y a un bon tutoriel sur les données de base et NSUndoManager . Hope qui aide.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top