NSManagedObject 的副本

Posted

技术标签:

【中文标题】NSManagedObject 的副本【英文标题】:A copy of a NSManagedObject 【发布时间】:2013-12-03 15:12:19 【问题描述】:

当我将copy 消息发送到NSManagedObject 子类时,我收到此错误:

'NSInvalidArgumentException',原因:'-[JTPModel copyWithZone:]: unrecognized selector sent to instance 0x8d19a10'

为什么我不应该复制NSManagedObjects

【问题讨论】:

通常要创建一个副本,您将创建一个新的 nsmanagedobject 并从原始对象中复制属性。这样你就有了两个具有相同属性的对象,但它们是两个不同的对象。您可以通过获取他们的 objectID 来检查,他们会有所不同。 【参考方案1】:

@aleroot 的链接很好。对于为什么这个基本问题,问题是对于应该如何进行复制没有单一的答案。您必须决定如何复制您的对象。这适用于所有面向对象语言中的所有对象,而不仅仅是NSManagedObject

考虑一个父对象有两个子对象和一个父对象居住的城市对象的情况。如果我复制父对象,我是否也应该复制子对象?可能是的,因为您不希望同一个孩子有多个父母。我应该复制城市吗?可能不会,因为每个人都没有自己的芝加哥副本。你应该在那里建立一个新的链接。您只能知道这一点,因为您知道对象代表什么。只有程序员才能实现这个逻辑。

一些面向对象的语言为所有对象提供了一个简单的“浅层”复制解决方案(这在上述情况下是不合适的)。 ObjC 为集合对象提供此功能,但不适用于通用对象。相反,您需要通过遵守<NSCopying> 协议来实施策略。

只是历史的一小部分:带注释的“属性”的语言支持在 ObjC 中是相当新的。几年前,对象知道它们的 ivars,但运行时没有关于它们的语义的有用信息(例如它们是副本、强引用还是弱引用)。这使得对象的自动复制变得非常困难,即使在简单的情况下也是如此。有一个名为NSCopyObject() 的自动浅拷贝功能,但它很容易出错并且caused much more trouble than it solved。幸运的是,它终于在 ios 6 和 OS X 10.8 中被弃用了。

【讨论】:

正如您所说,您描述的“问题”适用于所有对象的所有副本。那么:为什么可以解决其他类的对象而不是托管对象的问题?您没有给出具体原因,为什么可以解决 Cocoa 中许多很多类的深度“问题”,但不能解决托管对象。 NSCopyObject() 的问题不是决定要复制什么,不是决定如何复制,而是内存管理。这不是托管对象的具体问题。 无法解决其他泛型类的问题。 NSObject 不符合 <NSCopying>,就像 NSManagedObject 不符合一样。对于托管对象,这里没有特殊情况。它们与其他对象具有完全相同的问题。 不可能在 NSObject 中实现,因为它不知道要复制什么以及如何复制。托管对象在形式上是明确定义的。可以从可用的模型定义中读出所需的信息。情况不一样。例如,通用副本可以复制所有属性,从而使子类的代码更短。 (NSObject 的通用副本无法做出决定。)

以上是关于NSManagedObject 的副本的主要内容,如果未能解决你的问题,请参考以下文章

创建 NSManagedObject 属性值的副本

无论当前上下文状态如何,如何获取 NSManagedObject 的持久存储副本

过滤 NSManagedObject 的关系

c_cpp NSManagedObject类别,用于在另一个上下文中创建深层副本

Exchange 2013/2016延迟副本重播管理(Reply Log Manager)

如何在Swift中初始化iOS 10和iOS 9.3的NSManagedObject子类