objective-c cocoa core-data nsoperation nsmanagedobjectcontext

objective c - Deshacer las inserciones de datos principales que se realizan fuera del hilo principal



objective-c cocoa (5)

No soy un experto, pero creo que lo que vas a necesitar hacer es crear un segundo contexto para realizar las operaciones, luego unir los dos contextos. Debería poder administrar la combinación como un paso de deshacer. Tenga en cuenta que esto solo funciona si está tratando el conjunto completo de operaciones como un paso de deshacer, en lo que respecta al usuario.

Estoy trabajando en un código que usa una NSOperation para importar datos. Me gustaría que el usuario pueda deshacer las instancias NSManagedObject que se crean durante la operación de importación.

Por lo que puedo decir, es imposible usar NSManagedObjectContext -undoManager para cualquier operación que se realice fuera del hilo principal. Desde la sección de la Guía de programación de datos básicos sobre Usar confinamiento de subprocesos para admitir la simultaneidad , tenemos estas dos condiciones:

  1. Solo objectID se debe pasar entre contextos de objetos administrados (en hilos separados)
  2. Los objetos administrados se deben guardar en un contexto antes de que se pueda usar objectID.

Esto tiene sentido ya que los objetos administrados deben moverse desde el almacenamiento privado ( NSManagedObjectContext ) al almacenamiento público ( NSPersistentStore ) antes de que puedan ser compartidos.

Desafortunadamente, el mensaje -save: también hace que se eliminen los objetos administrados en la pila de deshacer. Desde la sección Administración de memoria utilizando datos básicos de la misma guía:

Los objetos administrados que tienen cambios pendientes (inserciones, eliminaciones o actualizaciones) son retenidos por su contexto hasta que se envíe su contexto a un mensaje de salvar :, restablecer, deshacer o destrabar, o la cantidad apropiada de deshacer para deshacer el cambio.

He intentado varias cosas para evitar esta limitación, y todo finalmente me lleva de vuelta a la mayor parte del trabajo que ocurre en el hilo principal (y bolas de playa giratorias). Cualquier pista para deshacer el trabajo con objetos creados fuera del hilo principal sería muy muy apreciado.

-

Se ha enviado un Radar de mejora: rdar: // problem / 8977725


Supongamos que utiliza un contexto separado para el hilo de fondo y, una vez hecho, [[backgroundContext undoManager] undo] un [[backgroundContext undoManager] undo] en la pila de deshacer del hilo de primer plano. Nunca he intentado algo así, pero por la parte más alta de mi cabeza no puedo pensar en una razón por la que no debería funcionar.


Una opción puede ser hacer que el hilo de importación sea persistente. Incluso cuando el hilo termina de importar, entra en un estado de bucle inactivo. De esta forma, su ManagedObjectContext enhebrado persistirá en el hilo adecuado. Luego, cuando el usuario desee deshacer un cambio, envíe un mensaje al hilo para usar el comando.


Es muy probable que haya considerado esto y es probable que solo esté buscando una solución utilizando el undoManager existente, pero por las undoManager :

Dado que está insertando objetos y no está actualizando los existentes, tiene la capacidad de etiquetarlos con una identificación de transacción a medida que se importa cada lote, eliminándolos en una cadena de fondo en el caso de un deshacer. Un simple NSNumber incrementado es suficiente para la etiqueta.

Inelegante, pero viable.


Esta respuesta probablemente será un poco de ida y vuelta. Si entiendo el problema correctamente, estás haciendo una importación pero cuando la importación está completa, ¿quieres que el usuario pueda seleccionar qué se guarda de la importación?

Si eso no es correcto, corrija mis suposiciones y actualizaré esta respuesta.

Si es correcto, entonces lo que puedes hacer es:

  1. Cambie la creación de objetos de fondo a

    NSEntityDescription *myEntity = ... //Entity from your context [[NSManagedObject alloc] initWithEntity:myEntity insertIntoManagedObjectContext:nil];

  2. Almacene estas entidades en una matriz.
  3. Pase las entidades a su hilo principal según sea necesario.
  4. Suelte cualquier objeto que no quiera mantener
  5. Llame a [myMainContext insertObject:managedObject] en cualquiera que desee conservar.
  6. Realice una NSManagedObjectContext guardar en NSManagedObjectContext .

Dado que estas entidades no son parte de un NSManagedObjectContext , solo existen en la memoria y deben ser seguras para la ejecución de subprocesos, ya que aún no están vinculadas a NSManagedObjectContext .

Esto es por supuesto teórico y requerirá pruebas. Sin embargo, debe lograr su objetivo.