在 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
属性,然后从块外的对象中提取所需的内容。
鉴于 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
属性,然后从块外的对象中提取所需的内容。