Pregunta

Estoy intentando crear una aplicación iPhone en el que el usuario puede añadir entradas. Cuando se presiona una nueva entrada, una caja de pop-up le pide alguna información. Entonces se puede pulsar "Cancelar" o "Guardar" para descartar los datos o guardarlo en el disco.

Para ahorrar, estoy usando el marco de Datos Básicos, que funciona bastante bien. Sin embargo, no puedo obtener el botón "Cancelar" para el trabajo. Cuando aparezca la ventana, pedir información, se crea un nuevo objeto en el contexto de objeto gestionado (MOC). Luego, cuando el usuario presiona Cancel, trato de utilizar el NSUndoManager perteneciente al Ministerio de Comercio.

También me gustaría hacer que el uso de grupos de deshacer anidados, porque puede haber grupos anidados.

Para probar esto, me escribió una sencilla aplicación. La aplicación es sólo la plantilla "aplicación basada en la ventana" con datos básicos habilitado. Para el modelo de datos básicos, se crea una sola entidad denominada "Entidad" con el atributo entero "x". A continuación, en el interior del applicationDidFinishLaunching, añado este código:

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

La idea es simple. Trate de insertar un nuevo objeto Entidad, deshacerlo, trae todos los objetos de entidad en el Ministerio de Comercio e imprimirlos. Si todo funcionó correctamente, no debe haber ningún objeto al final.

Sin embargo, me da este resultado:

[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

Como se puede ver, el objeto está presente en el MOC después de que intento de deshacer su creación. Cualquier sugerencia en cuanto a lo que estoy haciendo mal?

¿Fue útil?

Solución

Su problema es causado por el hecho de que, a diferencia de OS X, el iPhone logró contexto del objeto no contiene un administrador de deshacer por defecto. Es necesario agregar explícitamente una.

Cambiar el código generado en el delegado de la aplicación para la propiedad managedObjectContext a tener este aspecto:

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

}

Después de hacer ese cambio, el segundo mensaje de registro ya no se imprime.

Espero que ayude ...

David

Otros consejos

He intentado enfoque de Dave, pero no funcionó para mí. Finalmente encontré la solución en el ejemplo de Apple CoreDataBooks

El truco es crear un nuevo contexto que comparte el coordinador contigo contexto de aplicación. Para descartar los cambios que no tienes que hacer nada, simplemente descartar el nuevo objeto de contexto. Ya que comparten el coordinador, el ahorro de actualizaciones de su marco principal.

Aquí está mi versión adaptada, donde utilizo un objeto estático para el contexto temporal para crear un nuevo objeto 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;
}

espero que ayude

Gonso

Se debe trabajar. ¿Ha asignado correctamente undomanager a su managedObjectContext? Si usted ha hecho con razón que, por defecto tiene habilitado el registro de deshacer, y usted debe ser bueno para ir. Hay un buen artículo sobre datos básicos aquí . Hay un buen tutorial sobre datos básicos y NSUndoManager aquí . Espero que ayude.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top