如何在类之间传输 NSManagedObject 子类?

Posted

技术标签:

【中文标题】如何在类之间传输 NSManagedObject 子类?【英文标题】:How to transport NSManagedObject subclass between classes? 【发布时间】:2012-05-14 12:53:20 【问题描述】:

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

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

【问题讨论】:

你能进一步解释你的问题吗?您的问题是您无法在存储库层之外创建新的托管对象,还是您以后无法保存对象? 问题是上下文“隐藏”在存储库层内,我不想将其泄漏到存储库层之外。我想用它作为一个坚实的抽象点。 您知道每个托管对象都有一个指向托管对象上下文的指针吗?所以那只特定的猫是从袋子里出来的,有点。 是的,但是听着。我想在控制器中创建一个 Item 对象......然后将它传递给上下文所在的服务和存储库层。在 Java EE (JPA) 中执行此操作,对象不是附加到上下文的。 【参考方案1】:

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

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

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

【讨论】:

【参考方案2】:

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

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

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

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

【讨论】:

【参考方案3】:

编写复制粘贴了一个示例项目,该项目对模型自定义类隐藏了上下文: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

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

【讨论】:

以上是关于如何在类之间传输 NSManagedObject 子类?的主要内容,如果未能解决你的问题,请参考以下文章

将项目从 NSArray 传输到 NSManagedObject 的 NSSet

如何使用 NSManagedObject 对象在视图控制器之间传递自定义属性?

如何在 coredata/NSManagedObject 模型数据更改与应用程序用户界面之间进行紧密耦合?

NSManagedObject 能否符合 NSCoding

在 ViewController 之间传递 NSManagedObject

在 NSManagedObject 类中获取和保存数据的函数