2012-05-14 7 views
5

Hemos creado una capa de repositorio para interactuar con los datos principales que tienen métodos como allItems(), addItem:(Item*)item donde el elemento es la subclase NSManagedObject. Cuando necesitamos guardar un elemento, invocamos el método en el repositorio que pasa la instancia de la subclase como argumento. Sin embargo, eso no funciona porque no podemos usar el inicializador init y el contexto está oculto dentro del repositorio.Cómo transportar la subclase NSManagedObject entre clases?

¿Cuál es la mejor forma de transferir objetos cuando tienes una arquitectura como esta? ¿Hacer que un ItemDTO pase por una opción? ¿O hay mejores formas de resolver esto, como no usar NSManagedObject subclasificado en absoluto y simplemente usar la clave/valor que funciona?

+0

¿Puede explicar su problema un poco más? ¿Su problema es que no puede crear nuevos objetos gestionados fuera de la capa de repositorio, o que no puede guardar los objetos más adelante? – jrturton

+0

El problema es que el contexto está "oculto" dentro de la capa de repositorio y no quiero filtrar eso fuera de la capa de repositorio. Quiero usar eso como un punto sólido de abstracción. – LuckyLuke

+1

¿Sabe que cada objeto gestionado tiene un puntero al contexto del objeto gestionado? Entonces ese gato en particular está fuera de la bolsa, más o menos. – jrturton

Respuesta

1

I escribió copió-pegó un proyecto de ejemplo que oculta el contexto de las clases personalizadas del modelo: branch 10583736.

(que no es el código de producción final, sólo un ejemplo rápido, no espere que lidiar con múltiples hilos o errores extraños)

ocultar el contexto de clases personalizadas es sólo una cuestión de la definición de métodos personalizados de trata con cada situación donde normalmente solicitarás el contexto y lo usarás.

Se puede definir una clase para la capa de tienda de sin exponer el contexto:

@interface DataStore : NSObject 

+ (id)shared; 

- (void)saveAll; 
- (NSEntityDescription *)entityNamed:(NSString *)name; 
/* more custom methods ... */ 
- (NSManagedObject *)fetchEntity:(NSEntityDescription *)entity withPredicate:(NSPredicate *)predicate; 

@end 

Es mejor utilizar un ancestro común para todas las clases del modelo a medida para ahorrar algo de mecanografía. Esta clase puede ser la única que interactúa directamente con DataStore. No tiene acceso al contexto.

@interface DataObject : NSManagedObject 

+ (NSString *)entityName; 
+ (NSEntityDescription *)entity; 
- (void)save; 
/* more custom methods ... */ 

@end 

Finalmente clases personalizadas modelo define ningún método que debe, probablemente, aprovechando todo lo que está proporcionada por la superclase:

@interface Card : DataObject 

@property (nonatomic, retain) NSString * question; 
@property (nonatomic, retain) NSString * answer; 
@property (nonatomic, retain) Deck *deck; 

/* return a new card */ 
+ (Card *)card; 

/* more custom methods ... */ 

@end 

El maestro rama tiene un enfoque más habitual en el que las clases del modelo obtienen la contexto y trabajar con eso.

3

Normalmente, desea que los controladores que crean las subclases NSManagedObject tengan un puntero al NSManagedObjectContext. De esta forma, puedes llamar al inicializador.

El problema con lo que está tratando de hacer es que los elementos no pueden existir sin el contexto. Esto se hace deliberadamente para que Core Data sepa si está hablando de un nuevo objeto o un objeto que ya se encuentra en el almacén persistente.

Podría usar DTO pero terminaría con mucha duplicación por lo que se pone feo rápido. En mi opinión, debería considerar hacer que sus controladores tomen conciencia del contexto de Core Data para que pueda recuperar o iniciar los ítems (objetos administrados) y esencialmente usar el NSManagedObjectContext como su capa de repositorio.

Recuerde que NSManagedObjectContext ES una capa de abstracción de persistencia y puede realizar una copia de seguridad con otras implementaciones de tienda persistentes si lo desea, incluido su propio custom ones.

5

Diría que la arquitectura que está utilizando no es adecuada para los datos básicos. Para seguir usándolo (lo cual deberías) tienes que hacer una de dos cosas. Supongo que su "capa de repositorio" se implementa como un singleton, o al menos que los objetos que crean nuevos objetos administrados tienen acceso a ella.

  • Exponga su contexto de objeto gestionado a otros objetos, generalmente como una propiedad en su capa de repositorio.
  • Haga que su capa de repositorio se inicialice y devuelva los objetos por usted. Esto implicaría pasar un nombre de entidad y recuperar un nuevo objeto gestionado del tipo o clase de entidad apropiada.

Si te encuentras luchando contra los marcos y llegando a abstracciones excesivas, lo estás haciendo mal.

+0

La última opción fue buena, ¡gracias! Muy inteligente – LuckyLuke

Cuestiones relacionadas