2012-05-14 3 views
5

Мы создали слой репозитория для взаимодействия с основными данными, которые имеют такие методы, как allItems(), addItem:(Item*)item, где элемент является подклассом NSManagedObject. Когда нам нужно сохранить элемент, мы вызываем метод в репозитории, передавая экземпляр подкласса в качестве аргумента. Однако это не работает, потому что мы не можем использовать инициализатор init, и контекст скрыт внутри репозитория.Как переносить подкласс класса NSManagedObject между классами?

Каков наилучший способ передачи объектов при наличии такой архитектуры? Делает ли ItemDTO мимоходом что-то вроде опции? Или есть лучшие способы решить эту проблему, например, вообще не использовать подклассы NSManagedObject и просто использовать ключ/значение, которое работает.

+0

Не можете почитать ваши проблемы чуть позже? Ваша проблема в том, что вы не можете создавать новые управляемые объекты за пределами уровня репозитория или что вы не можете сохранить объекты позже? – jrturton

+0

Проблема заключается в том, что контекст «скрыт» внутри слоя репозитория, и я не хочу терять его за пределами уровня репозитория. Я хочу использовать это как сплошную точку абстракции. – LuckyLuke

+1

Вы знаете, что каждый управляемый объект имеет указатель на контекст управляемого объекта? Так что конкретная кошка вышла из сумки, вроде. – jrturton

ответ

1

I написал копировал пример проекта, который скрывает контекст от пользовательских классов модели: branch 10583736.

(это не окончательный код производства, просто быстрый пример, не следует ожидать, что иметь дело с многопоточностью или странными ошибками)

Скрытием контекста для пользовательских классов является лишь вопросом определения пользовательских методов иметь дело с любой ситуацией, когда вы обычно запрашиваете контекст и используете его.

Вы можете определить класс для хранения слоя , не подвергая контекст:

@interface DataStore : NSObject 

+ (id)shared; 

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

@end 

Я предлагаю использовать общий предок для всех пользовательских классов моделей, чтобы сохранить некоторые печатать. Этот класс может быть единственным, который напрямую взаимодействует с DataStore. Он не имеет доступа к контексту.

@interface DataObject : NSManagedObject 

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

@end 

Наконец вашей модели пользовательских классов определяет любой метод, который вы должны, вероятно, воспользовавшись то, что обеспечивается суперкласса:

@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 

мастер филиал имеет более привычный подход, при котором модели классов получить контекст и работать с ним.

3

Как правило, вы хотите, чтобы контроллеры, создающие подклассы NSManagedObject, имели указатель на NSManagedObjectContext. Таким образом, вы действительно можете вызвать инициализатор.

Проблема с тем, что вы пытаетесь сделать, состоит в том, что элементы не могут существовать без контекста. Это делается специально, так что Core Data знает, если вы говорите о новом объекте или объекте, который уже находится в постоянном хранилище.

Вы можете использовать DTO, но в итоге у вас будет много дублирования, поэтому он станет уродливым. На мой взгляд, вы должны подумать о том, чтобы ваши контроллеры знали о контексте Core Data, чтобы он мог правильно извлекать или инициализировать элементы (управляемые объекты) и по существу использовать NSManagedObjectContext в качестве уровня вашего репозитория.

Помните, что NSManagedObjectContext - это уровень абстракции настойчивости, и вы можете создать резервную копию с помощью других постоянных реализаций хранилища, если хотите, включая ваши собственные custom ones.

5

Я бы сказал, что используемая вами архитектура не подходит для данных ядра. Чтобы продолжать использовать его (что вам нужно), вам нужно сделать одну из двух вещей. Я предполагаю, что ваш «уровень репозитория» реализован как одноэлементный, или, по крайней мере, для доступа к нему объекты, создающие новые управляемые объекты.

  • Экспозиция контекста управляемого объекта к другим объектам, обычно как свойство на вашем уровне репозитория.
  • Попробуйте инициализировать слой вашего репозитория и вернуть объекты для вас. Это связано с передачей имени объекта и возвратом нового управляемого объекта соответствующего типа или класса объекта.

Если вы обнаружите, что сражаетесь с каркасами и придумываете чрезмерные абстракции, вы делаете это неправильно.

+0

Последний вариант был хороший, спасибо! Очень умно – LuckyLuke

Смежные вопросы