5

我们已经创建了一个存储库层,用于与 Core Data 进行交互,它具有诸如 的方法allItems()addItem:(Item*)item其中 item 是 NSManagedObject 子类。当我们需要保存一个项目时,我们调用存储库上的方法,将子类实例作为参数传递。但是,这不起作用,因为我们不能使用init初始化程序并且上下文隐藏在存储库中。

当您拥有这样的架构时,传输对象的最佳方式是什么?让 ItemDTO 绕过一个选项?或者有没有更好的方法来解决这个问题,比如根本不使用子类 NSManagedObject 而只使用有效的键/值。

4

3 回答 3

5

我想说您使用的架构不适合核心数据。要继续使用它(你应该这样做),你必须做两件事之一。我假设您的“存储库层”是作为单例实现的,或者至少创建新托管对象的对象可以访问它。

  • 将托管对象上下文公开给其他对象,通常作为存储库层上的属性。
  • 让您的存储库层初始化并为您返回对象。这将涉及传入实体名称并取回适当实体类型或类的新托管对象。

如果您发现自己在与框架作斗争并提出过多的抽象,那么您做错了。

于 2012-05-21T20:55:47.577 回答
3

通常,您希望创建NSManagedObject子类的控制器具有指向NSManagedObjectContext. 这样,您确实可以调用初始化程序。

您尝试做的问题是,如果没有上下文,这些项目就无法存在。这是故意这样做的,以便 Core Data 知道您是在谈论新对象还是已经在持久存储中的对象。

您可以使用 DTO,但最终会产生大量重复,因此很快就会变得丑陋。在我看来,您应该考虑让您的控制器了解 Core Data 上下文,以便它可以正确地检索或初始化项目(托管对象)并基本上将其NSManagedObjectContext用作您的存储库层。

请记住,NSManagedObjectContextIS 是一个持久性抽象层,如果需要,您可以使用其他持久性存储实现来备份它,包括您自己的自定义实现。

于 2012-05-21T19:14:49.683 回答
1

编写了复制粘贴的示例项目,该项目从模型自定义类中隐藏了上下文:分支 10583736

(这不是最终的生产代码,只是一个简单的例子,不要指望它会处理多线程或奇怪的错误)

将上下文隐藏到自定义类只是定义自定义方法以处理您通常会请求上下文并使用它的每种情况。

您可以在不暴露上下文的情况下为 store 层定义一个类:

@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

master分支有一种更常用的方法,模型类获取上下文并使用它。

于 2012-05-26T18:38:20.803 回答