Ios 按objectID获取NSManagedObject数组返回空数组
我正在尝试执行一个fetch,使用从单独的上下文中收集的对象ID数组从上下文中检索托管对象。但是,获取返回的是一个空数组 从“核心数据编程指南”的“检索特定对象”部分 : 如果应用程序使用多个上下文,并且要测试对象是否已从持久存储中删除,则可以使用self==%@形式的谓词创建一个获取请求。作为变量传入的对象可以是托管对象或托管对象ID…” 如果需要测试是否存在多个对象,则使用IN运算符比为单个对象执行多个回迁更有效,例如: NSPredicate*谓词=[NSPredicate谓词格式:@“self IN%@”, ArrayOfManagedObjects] 在讨论对象删除测试时,我假设如果未删除对象,则结果数组不是空的,并且将包含实际的NSManagedObjects。但是,当我执行此代码时:Ios 按objectID获取NSManagedObject数组返回空数组,ios,objective-c,core-data,Ios,Objective C,Core Data,我正在尝试执行一个fetch,使用从单独的上下文中收集的对象ID数组从上下文中检索托管对象。但是,获取返回的是一个空数组 从“核心数据编程指南”的“检索特定对象”部分 : 如果应用程序使用多个上下文,并且要测试对象是否已从持久存储中删除,则可以使用self==%@形式的谓词创建一个获取请求。作为变量传入的对象可以是托管对象或托管对象ID…” 如果需要测试是否存在多个对象,则使用IN运算符比为单个对象执行多个回迁更有效,例如: NSPredicate*谓词=[NSPredicate谓词格式:@“s
- (NSArray *)managedObjectsOfEntityName:(NSString *)entityName fromObjectIDs:(NSArray *)objectIDs managedObjectContext:(NSManagedObjectContext *)managedObjectContext
{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];
request.predicate = [NSPredicate predicateWithFormat:@"self IN %@", objectIDs];
__autoreleasing NSError *error = nil;
NSManagedObjectID *testID = objectIDs[0];
NSManagedObject *obj = [managedObjectContext existingObjectWithID:testID error:&error];
if (!obj)
{
NSLog(@"Unable to perform fetch. Error: %@", error);
}
error = nil;
NSArray *results = [managedObjectContext executeFetchRequest:request error:&error];
if (!results)
{
NSLog(@"Unable to perform fetch. Error: %@", error);
}
return results;
}
results
数组为非nil且为空,而obj
已正确填充
我已经添加了对existingObjectWithID:
的显式调用,作为一个健全性检查,它会返回预期的对象,没有错误
以下是相关变量的调试器输出:
(lldb) po entityName
Foo
(lldb) po objectIDs
<__NSArrayI 0x1170d4950>(
0xd0000000055c0082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p343>,
0xd000000008e80082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p570>,
0xd000000008840082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p545>,
0xd000000006040082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p385>,
0xd000000007740082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p477>,
0xd000000008280082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p522>,
0xd000000008e40082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p569>
)
(lldb) po request
<NSFetchRequest: 0x10f338840> (entity: Foo; predicate: (SELF IN {
0xd0000000055c0082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p343>,
0xd000000008e80082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p570>,
0xd000000008840082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p545>,
0xd000000006040082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p385>,
0xd000000007740082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p477>,
0xd000000008280082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p522>,
0xd000000008e40082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p569>});
sortDescriptors: ((null)); type: NSManagedObjectResultType; )
(lldb) po request.predicate
SELF IN {
0xd0000000055c0082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p343>,
0xd000000008e80082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p570>,
0xd000000008840082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p545>,
0xd000000006040082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p385>,
0xd000000007740082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p477>,
0xd000000008280082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p522>,
0xd000000008e40082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p569>}
(lldb) po testID
0xd0000000055c0082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p343>
(lldb) p testID.isTemporaryID
(bool) $7 = false
(lldb) p obj
(NSManagedObject *) $9 = 0x000000010f338630
(lldb) po results
<__NSArrayI 0x10f205c70>(
)
(lldb) po testID.entity
nil
(lldb)采购订单实体名称
福
(lldb)采购订单对象
(
0xd0000000055c0082,
0xd000000008e80082,
0xd000000008840082,
0xd000000006040082,
0xd000000007740082,
0xd000000008280082,
0xd000000008e40082
)
(lldb)采购订单请求
(实体:Foo;谓词:(SELF-IN){
0xd0000000055c0082,
0xd000000008e80082,
0xd000000008840082,
0xd000000006040082,
0xd000000007740082,
0xd000000008280082,
0xd000000008e40082});
sortDescriptors:((null));类型:NSManagedObjectResultType;)
(lldb)po request.predicate
自恋{
0xd0000000055c0082,
0xd000000008e80082,
0xd000000008840082,
0xd000000006040082,
0xd000000007740082,
0xd000000008280082,
0xd000000008e40082}
(lldb)po testID
0xd0000000055c0082
(lldb)p testID.isTemporaryID
(bool)$7=错误
(lldb)p obj
(NSManagedObject*)$9=0x000000010f338630
(lldb)采购订单结果
(
)
(lldb)采购订单测试实体
无
testID
上的nil
实体
很奇怪,但我不确定这是否“坏”
因此,我显然不知道为什么fetch返回为空。实体名称正确,fetch和谓词看起来不错,对象在上下文中,但仍然没有结果
附加上下文:
本质上,更大的情况是我有一个后台操作,它使用自己的托管对象上下文(MOC)执行一些工作。工作的结果需要在主队列上,因此我打包工作产生的objectID并将其传递给主队列。在主队列上,我需要返回实际的托管对象,因此我尝试通过objectID从主队列的MOC获取它们。我意识到我可以使用objectWithID:
或MOC上的existingObjectWithID:error:
或甚至objectRegisteredForID:
来获取这些对象,但每个对象都有自己的特殊问题:
如果对象不在上下文中,则可能返回一个伪造的对象,如果对象在上下文中,则将返回一个错误objectWithID:
非常好,因为我们将返回existingObjectWithID:error:
(而不是伪对象),但它也会返回错误nil
如果对象不在上下文中,则返回objectRegisteredForID:
nil
objectWithID:
或existingObjectWithID:error:
来获取一组对象,这可能是n
到持久化存储区对对象进行故障处理,这意味着性能可能会非常糟糕。如果我使用objectRegisteredForID:
我可能根本无法获取对象如果它恰好不在主队列的MOC中
因此,我希望fetch请求能够限制与持久性存储交互的开销,并一次性返回我所需的所有对象,而不是尝试遍历数组
添加:
顺便说一句,这个问题确实与
@“self IN%@”
谓词有关,因为我可以删除该谓词并毫无疑问地获取entityName
的所有对象。我还尝试了@“objectID IN%@”
作为具有相同(零)的谓词结果。好的,准备好进入核心数据兔洞了吗
TL;DR
NSManagedObjectID
s的持久存储协调器不再在内存中,它将丢失其NSEntityDescription
(entity
)并且不相等(isEqual:
返回no
)从不同的持久存储协调器发送到NSManagedObjectID
s,即使它们的URIRepresentation
相同
从兔子洞里钻下去
亲爱的…我们开始吧
记住,我在一个单独的线程上从一个单独的托管对象上下文(MOC)收集ObjectID数组?很好。但是,我没有提到MOC正在使用它自己的持久存储协调器(PSC)(当然,指向同一个文件)。PSC和MOC的寿命很短,因为一旦工作完成,它们就会自动删除,但当它们处于活动状态时,我会将NSManagedObjectID
的实例保存到NSArray
(传递到另一个线程)
在单独的线程中收到后,NSManagedObjectID
s有一个nil
实体。这似乎正在发生(这里是有根据的猜测…),因为
NSURL *URIRep = objectID.URIRepresentation;
NSManagedObjectID *newObjectID = [managedObjectContext.persistentStoreCoordinator managedObjectIDForURIRepresentation:URIRep];
(lldb) p [ojectID isEqual:newObjectID]
(bool) $0 = false
NSManagedObject *obj = [managedObjectContext existingObjectWithID:testID error:&error];