Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/99.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 按objectID获取NSManagedObject数组返回空数组_Ios_Objective C_Core Data - Fatal编程技术网

Ios 按objectID获取NSManagedObject数组返回空数组

Ios 按objectID获取NSManagedObject数组返回空数组,ios,objective-c,core-data,Ios,Objective C,Core Data,我正在尝试执行一个fetch,使用从单独的上下文中收集的对象ID数组从上下文中检索托管对象。但是,获取返回的是一个空数组 从“核心数据编程指南”的“检索特定对象”部分 : 如果应用程序使用多个上下文,并且要测试对象是否已从持久存储中删除,则可以使用self==%@形式的谓词创建一个获取请求。作为变量传入的对象可以是托管对象或托管对象ID…” 如果需要测试是否存在多个对象,则使用IN运算符比为单个对象执行多个回迁更有效,例如: NSPredicate*谓词=[NSPredicate谓词格式:@“s

我正在尝试执行一个fetch,使用从单独的上下文中收集的对象ID数组从上下文中检索托管对象。但是,获取返回的是一个空数组

从“核心数据编程指南”的“检索特定对象”部分 :

如果应用程序使用多个上下文,并且要测试对象是否已从持久存储中删除,则可以使用self==%@形式的谓词创建一个获取请求。作为变量传入的对象可以是托管对象或托管对象ID…”

如果需要测试是否存在多个对象,则使用IN运算符比为单个对象执行多个回迁更有效,例如:

NSPredicate*谓词=[NSPredicate谓词格式:@“self IN%@”, ArrayOfManagedObjects]

在讨论对象删除测试时,我假设如果未删除对象,则结果数组不是空的,并且将包含实际的NSManagedObjects。但是,当我执行此代码时:

- (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];