NSManagedObjectContext的userInfo属性如何工作?

时间:2014-10-05 19:01:19

标签: cocoa core-data

在当前标题中,它被声明为:

@property (nonatomic, readonly, strong) NSMutableDictionary *userInfo NS_AVAILABLE(10_7,  5_0);

文档只是说:

  

返回接收者的用户信息。

  1. 上下文userInfo的目的是什么? Other Core Data objects可以在托管对象模型中设置userInfo个词典。这似乎不是这种情况。它只是作为临时存储而不是使用关联对象吗?

  2. 是否曾保存到持久性商店或通过NSCoding

  3. 它是否使用与上下文的托管对象相同的线程模型?

2 个答案:

答案 0 :(得分:2)

上下文的userInfo是什么目的?

我看了几个方法,遗憾的是没有找到任何确定的方法。

  • -[NSManagedObjectContext userInfo]上设置一个符号断点,并运行一组核心数据回归测试,这些测试可以运行大部分公共API。
  • 使用多种逆向工程工具查看Core Data二进制框架。

使用符号断点并没有产生太大的影响,尽管我使用的Xcode版本可能只是吹过它。看起来任何东西都没有访问公共访问者,但考虑到核心数据的内部结构并不令人惊讶。

拆解该方法产生了一些提示:

void * -[NSManagedObjectContext userInfo](void * self, void * sel) {
    rsi = sel;
    rbx = self;
    if (*(int32_t *)__PF_Threading_Debugging_level != 0x0) {
            __PFAssertSafeMultiThreadedAccess_impl(rbx, rsi);
    }
    rax = *_OBJC_IVAR_$_NSManagedObjectContext._additionalPrivateIvars;
    rax = *(rbx + rax);
    rax = *(rax + 0x30);
    return rax;
}

该方法确实检查了并发调试是否处于活动状态,并且在并发规则中正确使用了此方法(这回答了问题3)。该方法直接访问私有实例变量_additionalPrivateIvars,其中Core Data的其他部分从中读取和写入。一些更改跟踪/进度和乐观锁定方法使用此实例变量。例如,-lockObjectStore会在_additionalPrivateIvars上写NSManagedObjectContext

有点奇怪,NSMutableDictionary是只读的。您无法设置新的NSMutableDictionary,但您可以愉快地在其上设置键和值。我很容易做到这一点:

(lldb) po [[[result managedObjectContext] userInfo] setValue:@"foo" forKey:@"bar"]
0x0000000000000020

(lldb) po [[result managedObjectContext] userInfo]
{
    bar = foo;
}

如果没有Apple的更详细指导,我不希望在生产代码中执行此操作,因为写入此内容可能很危险。

是否曾保存到持久存储或通过NSCoding?

它似乎不是,并且这样做没有多大意义。持久性商店对通过协调器访问它们的上下文一无所知,如果userInfo字典对于商店很重要,那么它应该包含在原子商店编程指南和增量存储编程指南中。

它是否使用与上下文的托管对象相同的线程模型?

肯定会这样做,如果并发调试是主动的,误用-userInfo会记录一个断言。

答案 1 :(得分:0)

此特定API的文档非常稀疏(总文本为:The receiver’s user info.)。但是,userInfo字典在Apple的框架中非常标准。用户可以在不需要创建子类的情况下添加自定义信息(例如,参见NSNotification userInfo上的documentation)。

NSManagedObjectContext的{​​{1}}只读是一个问题。而不是像你期望的那样将属性分配给字典:

userInfo

直接访问字典(毕竟,它是可变的):

// useful while debugging multiple Core Data threads
*moc.userInfo = @{@"name":@"main managed object context"};