Pregunta

Tengo el siguiente modelo, como se puede ver en la imagen.

alt text http://img521.imageshack.us/img521/9741/schermata20100224a12251 .png

Mi aplicación requiere actualizar todas las instancias de B, por lo que en cada viewWillAppear, necesito borrar todo el B en el modelo. Tras la eliminación de un B, la norma de supresión en cascada sobre la relación de C borrará todos los C y luego en cascada a todos D. A & E son constantes.

Tengo el DeleteRule en cada objeto como sigue:

A: b - Cascade
B: c - Cascade, a - Nullify
C: b - Nullify, d - Cascade
D: c - Nullify, e - Nullify
E: d - Cascade

o

A -(cascade)->> B -(cascade)-> C -(cascade)->> D -(nullify)-> E
A <-(nullify)- B <-(nullify)- C <-(nullify)- D <-(nullify) E

Estoy teniendo un problema con la conexión en cascada de borrar en todos los B, C, D. Mi objetivo fetchRequest regresa cada instancia de B en A y luego llamar a la -deleteObject: en cada B de la managedObjectContext. Pero existe la EXC_BAD_ACCESS en la llamada a [managedObjectContext ahorra: y error].

Puede alguien me muestre lo que estoy haciendo mal? Tengo problemas con la DeleteRule de cada entidad o ¿El problema estaba en otra parte? ¿Cuáles son las mejores prácticas para manejar las eliminaciones en cascada en tres objetos B, C, D?

Editado:

Aquí está el seguimiento de la pila cuando se eleva el error:

  #0    0x01d843ae in ___forwarding___
  #1    0x01d606c2 in __forwarding_prep_0___
  #2    0x01c618b6 in -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:]
  #3    0x0003263a in _nsnote_callback
  #4    0x01d4f005 in _CFXNotificationPostNotification
  #5    0x0002fef0 in -[NSNotificationCenter postNotificationName:object:userInfo:]
  #6    0x01bc217d in -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:]
  #7    0x01c21763 in -[NSManagedObjectContext(_NSInternalChangeProcessing) _createAndPostChangeNotification:withDeletions:withUpdates:withRefreshes:]
  #8    0x01ba65ea in -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:]
  #9    0x01bdc728 in -[NSManagedObjectContext save:]

Aquí está el registro en la consola cuando traté de establecer NSZombieEnabled y MallocStackLogging a SÍ:

  2010-02-24 15:41:39.803 Foo[2591:207] deleting object: FUM5
  2010-02-24 15:41:40.515 Foo[2591:207] *** -[viewController controllerWillChangeContent:]: message sent to deallocated instance 0x7e54510

Editar 2: CÓDIGO FUENTE AÑADIDO

Me han tratado de recrear la situación mediante la creación de un nuevo proyecto con el esquema exacto de la imagen. Puede descargarlo desde aquí . Hay un texto README también. Esperanza de que he dado suficiente información.

¿Fue útil?

Solución

¿Qué haces en tus métodos NSFetchedResultsControllerDelegate? Con base en el seguimiento de pila que parece que está haciendo algo gracioso en uno de esos. Lo ideal sería que los delegados sólo deben actualizando el UITableView que están unidos a. Si usted está haciendo algo, ya sea con las instancias NSManagedObject o la NSManagedObjectContext en uno de esos métodos que puede causar un accidente como éste.

Yo sugeriría poner un punto de interrupción en objc_exception_throw y que le puede dar más información sobre el punto exacto se está produciendo el problema.

Actualizar

He mirado el código y que está intentando eliminar un B mientras que A tiene una propiedad necesaria para que B. Esto está causando un error de validación. No se puede eliminar un objeto que tiene otro objeto como una relación necesaria.

Otros consejos

Creo que el problema podría sentar en una relación necesaria entre C y D. Si ha configurado el gráfico tal que:

  1. Cada C requiere al menos un D.
  2. Muchos casos de punto C a la misma D.

A continuación, en algún momento un C es probable que se encuentran con que su relación requerida ha sido anulado. Si se intenta acceder a la D de todos modos, que activará el EXC_BAD_ACCESS. (Si cada uno requiere E D podría obtener el mismo problema)

Para depurar Sugiero,

  • Establecer la relación C -> D como opcionales y ver si el error desaparece.
  • Cambiar las cascadas a los nulos de uno en uno a partir de C -.> D y ver si el error desaparece
  • Si tiene clases, comprobar que los casos no comparten algún objeto en común fuera del gráfico entidad. Por ejemplo, las dos clases C y D tienen una referencia a la misma imagen, pero esa imagen no es parte de la entidad. Si las referencias externas no se conserva adecuadamente que también puede causar un accidente similar.
  • mover su parada inmediatamente después de la llamada a eliminar cada registro de cada uno de B. B y de Cs antes de eliminar. De esa manera usted puede ver exactamente eran el proceso de almacenamiento falla y en qué estado está el gráfico está en cuando lo hace.

Edit01:

Bien, miré a su código y encontré el problema.

El problema es que usted tiene la relación "b" de un conjunto de requerido. Cuando se elimina B que arroja este error:

2010-02-24 16:14:02.064 CoreDataTestDeleteRule[20887:207] Unresolved error Error Domain=NSCocoaErrorDomain Code=1580 UserInfo=0x3d0b450 "Operation could not be completed. (Cocoa error 1580.)"
2010-02-24 16:14:06.340 CoreDataTestDeleteRule[20887:207] Unresolved error Error Domain=NSCocoaErrorDomain Code=1580 UserInfo=0x3d19980 "Operation could not be completed. (Cocoa error 1580.)", {
    NSLocalizedDescription = "Operation could not be completed. (Cocoa error 1580.)";
    NSValidationErrorKey = b;
    NSValidationErrorObject = <A: 0x3b2faf0> (entity: A; id: 0x3d05330 <x-coredata://6870AF7C-E28F-4B4E-80AB-09C648651179/A/p1> ; data: {
    b =     (
    );
    name = a;

( Por cierto, Los errores de texto para los códigos de error Core datos numéricos se pueden encontrar en CoreDataErrors.h. )

Esto tiene sentido porque se requiere una para tener una b y luego eliminar todos los b. Basta con establecer la A -. >> B previene relación con el error opcional y permite que el código se ejecute bien

código también tiene algunos otros problemas. Algunas de las clases de auto generada no se realice correctamente. Por ejemplo, la interfaz para B.h se ve así:

#import <CoreData/CoreData.h>

@class A;

@interface B :  NSManagedObject  
{
}

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) A * a;
@property (nonatomic, retain) NSManagedObject * c;

@end

Cuando se debe verse como:

#import <CoreData/CoreData.h>

@class A;
@class C;

@interface B :  NSManagedObject  
{
}

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) A * a;
@property (nonatomic, retain) C * c;

@end

No estoy seguro de por qué no se volvió a generar correctamente.

También aconsejaría contra el uso de los nombres de variables y de clase cortos. Objetivo-c tiene un espacio de nombres global y el uso de símbolos de una sola letra es una invitación para una colisión de nombres. Nunca se sabe quién más estaba en un apuro. Me recomendar usando el alfabeto fonético viejo estilo de la Segunda Guerra Mundial (la moderna también colisiones de riesgo) y el nombre de las clases de prueba: Adam, Baker, Charlie, David, Eddy etc.

Parece que los dos nos centramos en el B <-> C <- >> D relación y descuidado a mirar más allá. Es la versión de depuración del programador de "fijación de destino" de los militares. Se queda atascado en un concepto del problema y no se puede dejar atrás estas vivencias suelto.

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