在 NSOperation 中查找 NSManagedObject

Finding NSManagedObject inside of NSOperation

鉴于 objectID,我认为 [moc existingObjectWithID:self.objectID error:&error] 是在线程内查找现有对象的正确方法,但我无法让它工作,为什么?

背景/代码

我有一个 NSManagedObject 已经保存了。我可以在主线程上看到它的所有属性。我在自定义 init 方法中将对象传递给我的 NSOperation,在该方法中,我正在保存它的 objectID:

- (instancetype)initWithEntity:(NSManagedObject *)object
{
    self = [super init];
    if (self) {
        self.objectID = object.objectID;
        ...
    }
    return self;
}

然后在我的操作的 main 函数中查找我的对象以便我可以使用它。

- (void)main
{
    if (self.isCancelled) { return; }

    NSManagedObjectContext *moc = [NSManagedObjectContext MR_context];

    NSError *error = nil;
    self.object = [moc existingObjectWithID:self.objectID error:&error];

    if (error) {
        DDLogError(@"error finding object: %@", error);
    }

    ...
}

MR_context 是一种 MagicalRecord 方法,它简单地设置一个具有并发类型 NSPrivateQueueConcurrencyType 的新上下文,其父级设置为根保存上下文。所有这些对我来说都是正确的。

错误

当没有设置调试器时,我只是为对象得到一个 fault。如果我尝试在上面查找任何 属性,我会得到 nil.

打开调试器并设置 -com.apple.CoreData.ConcurrencyDebug 1 我得到了一些错误:

在模拟器中,我在 [moc existingObjectWithID:self.objectID error:&error] 行上得到 EXC_BAD_INSTRUCTION (code=EXC_i386_INVOP, subcode=0x0)

在设备上,我在同一行得到以下信息:

CoreData`+[NSManagedObjectContext __Multithreading_Violation_AllThatIsLeftToUsIsHonor__]:
->  0x185946614 <+0>: brk    #0x1

所以显然有问题,但 objectID 不是临时的,它与我在主线程上检查真实对象时看到的 objectID 相同。所以我不确定为什么它不起作用。

我也试过:

self.object = [moc objectWithID:self.objectID];

但这也不管用。有什么想法吗?

更新

2015-07-10 - 好的,如果我使用带有 moc 的块,那么我可以从该块中正确访问该对象。

[moc performBlock:^{
    NSError *error = nil;
    NSManagedObject *o = [moc existingObjectWithID:self.objectID error:&error];
}];

如何正确提取该对象,以便我可以在操作为 运行 的线程中访问它?执行 __block 属性 然后在块中设置它并在块外使用它失败。

这是 context 设置方式的问题吗?

MagicalRecord 的上下文设置了自己的队列来对其执行操作。因此,如果你想用它来查找某些东西,你必须在一个块([context performBlock:][context performBlockAndWait:])中进行,以便它可以在自己的队列中执行,然后 return 回到 NSOperation.

我最后做的是创建几个 __block 属性,然后从块外的对象中提取所需的内容。