【问题标题】:Why doesn't NSManagedObject instances hold a strong reference to their NSManagedObjectContext?为什么 NSManagedObject 实例不持有对其 NSManagedObjectContext 的强引用?
【发布时间】:2014-07-04 10:15:24
【问题描述】:

正如在 SO(和 Apple docs)上的 another question 中指出的那样,NSManagedObject 实例不会强烈引用它们所源自的 NSManagedObjectContext。乍一看,这似乎是一个奇怪的决定,因为没有 contextNSManagedObject 实例几乎毫无用处,因为它会导致诸如 faults not firing when they should 之类的混淆错误。

谁能提供一些背景说明为什么会这样?实现一个自动持有对其NSManagedObjectContext 的强引用的NSManagedObject 子类会不会很危险?

编辑:感谢对这个问题的出色回答,我发现我的托管对象是由 RestKit 针对一个有意临时的 NSManagedObjectContext 创建的。接下来是我的下一个问题,专门针对 RestKit,here

【问题讨论】:

    标签: ios objective-c core-data nsmanagedobject nsmanagedobjectcontext


    【解决方案1】:

    实现一个自动持有对其 NSManagedObjectContext 的强引用的 NSManagedObject 子类会很危险吗?

    正如其他人指出的那样,这会很危险,因为您会创建一个保留周期。

    更好的做法是订阅通知

    NSManagedObjectContextObjectsDidChange

    只要上下文通知您更改了对象,您就可以在此处更新对象。

    例子:

    - (void)addObservers
    {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(managedObjectContextChanged) name:NSManagedObjectContextObjectsDidChangeNotification object:_myManagedObjectContext];
    }
    
    - (void)managedObjectContextChanged
    {
        [self fetchObjects];
    }
    

    另外,正如 Apple 所指出的,一定要传递你想要观察的上下文:

    一些系统框架在内部使用 Core Data。如果您注册以从所有上下文接收这些通知(通过将 nil 作为对象参数传递给 addObserver(_:selector:name:object:) 等方法),那么您可能会收到难以处理的意外通知。

    【讨论】:

      【解决方案2】:

      NSManagedObjectContext 拥有其 NSManagedObjects 比相反的方式更有意义。

      请记住,上下文就像一个绘图板,上面有所有对象。如果该上下文消失,则对象不再有效。如果对象拥有上下文,那么上下文消失不会对对象产生任何影响,并且它们似乎仍然有效。换句话说:上下文可以没有对象而存在,对象不能没有上下文而存在。

      当然,混合模型(上下文拥有它的对象,对象拥有它们的上下文)也不会工作,因为那样你会遇到一个保留循环。

      NSManagedObject 实例在没有上下文的情况下几乎毫无用处

      它们可以是(尽管不一定),但请记住,它们确实引用了它们的上下文!大概它是一个弱参考,但仍然是一个参考。如果该引用返回 nil,对象无效。如果您确保您的上下文保持不变(这是我在回答另一个问题时所做的),那么您就不会有任何问题。

      【讨论】:

        【解决方案3】:

        这是因为否则你会得到一个保留周期。托管对象上下文在内部使用数组和其他容器,这些容器具有对托管对象的引用。

        可能,Core Data 的内部实现不能轻易地“显式破坏”这个保留循环,因此这个引用必须是弱的。

        【讨论】:

        • CouchDeveloper 是正确的,是的,从托管对象类添加对上下文的强引用可能会很危险。错误在“应该”时没有触发可能是由于很多原因,但大多数情况下是访问器方法的错误实现。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-20
        • 2011-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-23
        相关资源
        最近更新 更多