从 Core-Data 请求不同的 NSManagedObject 属性实例时返回啥类?

Posted

技术标签:

【中文标题】从 Core-Data 请求不同的 NSManagedObject 属性实例时返回啥类?【英文标题】:What class is returned when requesting distinct NSManagedObject property instances from Core-Data?从 Core-Data 请求不同的 NSManagedObject 属性实例时返回什么类? 【发布时间】:2013-11-07 15:59:51 【问题描述】:

我有一个简单的情况,我有一个 CDPerson 类,它是 NSManagedObject 的子类。此类包含与 CDHair 类(也是 NSManagedObject 的子类)的一对一关系。 CDPerson 类的关系属性名为“hair”。

我想了解 ManagedObjectContext 中所有 CDPerson 实例实际使用的不同 CDHair 实例。

我正在获取一个不同的属性列表(这部分有效),

 NSFetchRequest* fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Person"];
 fetchRequest.returnsDistinctResults = YES;
 fetchRequest.propertiesToFetch = @[@"hair"];
 fetchRequest.resultType =NSDictionaryResultType;
 fetchRequest.predicate=[NSPredicate predicateWithFormat:@"hat=='no'"];
 fetchRequest.returnsDistinctResults = YES;
 NSArray* fetchResults = [context executeFetchRequest:fetchRequest error:&error];

fetchResults 在 NSArray 中符合预期。 fetchResults[0] 是预期的 NSDictionary。 fetchResults[0][@"hair"] 解决了一些问题,但我不知道它是什么。它的 po 描述是

0x8b7b120 <x-coredata://C7E53293-94C7-444D-8162-167B1D66A961/Hair/p33>

它似乎没有选择器。如果我将它转换为 CDHair 并尝试使用实例上的属性,例如 .color,我会收到“无法识别的选择器”错误。

CDTest[2865:70b] -[_NSObjectID_48_0 color]: unrecognized selector sent to instance 0x8ba8670

首先,我不知道 _NSObjectID_48_0 类是什么。 其次,我认为从 fetch 中检索到的属性将是 CDHair 的 CoreData 实例,但情况似乎并非如此。也不是 NSManagedObject。

我哪里出错了?

【问题讨论】:

你能贴出你的fetchRequest的所有代码吗 您确定您在 fetchRequest 中指定的实体名称是 "CDHair" 吗? “/Hair/p33”表示它是一个实体名称为“Hair”且ID为“p33”的对象 为了记录,当你明确要求NSDictionaryResultType时,你不会得到任何NSManagedObjects。这意味着您不会得到隐含的错误或任何其他对象图的细节。另一方面,字典是线程安全的,并且可以保证不会意外触发对后备存储的任何访问 - 如果您正在进行多线程存储访问,则可能必须等待锁定被释放。跨度> 谢谢大家。我看到我真正缺少的是 [context objectWithID:] 来获取实际对象。 @RyanG 发布了所有 fetchRequest 代码。 【参考方案1】:

既然你已经明确设置了

fetchRequest.resultType = NSDictionaryResultType;

获取请求返回一个字典,并表示与其他对象的关系 通过NSManagedObjectID。您可以从“托管”中检索相应的对象 对象 id" 使用 objectWithIDexistingObjectWithID 方法。例如:

NSManagedObjectID *mid = fetchResults[0][@"hair"];
CDHair *hair = (CDHair *)[context objectWithID:mid];
NSString *color = hair.color;

但将propertiesToFetch 设置为CDHair 的实际属性可能更容易 你感兴趣的,例如

fetchRequest.propertiesToFetch = @[@"hair.color"];

那么结果数组会是这样的

( “头发。颜色”=绿色; , “头发.颜色”=红色; )

你可以像这样访问它

NSString *color = fetchResults[0][@"hair.color"];

【讨论】:

啊! [上下文 objectWithID:mid]! CoreData 有很多陷阱。谢谢! @SamuelRenkert:这就是为什么我也提到了 existingObjectWithID 以及避免对象 ID 的替代方法。不客气。【参考方案2】:

您要求CDPerson 实体的关系属性。这只会导致返回的字典被这些人的相关CDHairobjectID 填充。

结果字典中填充了与结果集的CDHair 元素(所有现有人员)相关的NSObjectID 对象。这就是为什么您不能直接使用这些对象来获取它们的属性的原因。您可以通过使用NSManagedObjectContextexistingObjectWithID:error:objectWithID: 并将返回的ID 传递给它来获取实际对象。

如果您喜欢不同的 CDHair 正在使用的对象,您可以将您的请求更改为: (假设逆向关系命名为persons

NSFetchRequest* req = [NSFetchRequest fetchRequestWithEntityName:@"CDHair"];
req.predicate = [NSPredicate predicateWithFormat:@"persons.@count != 0"];

这应该会为您提供所有不同的 CDHair 对象,这些对象正被您的商店中的 CDPersons 使用。

【讨论】:

酷。在我的测试中,我确实发现我得到了一个不同的 NSObjectID 列表,它反映了我期望的不同头发。我认为这是可行的,因为每个 CDHair 都有一个唯一的 ID,所有红发女郎共享同一个 CDHair 实例。我必须承认,我喜欢你对 fetch distinct 请求的实现,并且会转换为使用它,因为它会返回活动实例。 您对不同的结果是正确的,我已经编辑了我的答案以反映这一点【参考方案3】:

你试过这样获取颜色属性吗?

NSArray* fetchResults = [moc executeFetchRequest:fetchRequest error:&error];
for (NSDictionary* hair in fetchResults) 
  NSLog(@"Hair Color is:", [hair objectForKey:@"color"]);

【讨论】:

以上是关于从 Core-Data 请求不同的 NSManagedObject 属性实例时返回啥类?的主要内容,如果未能解决你的问题,请参考以下文章

IOS/objective-c/core-data:如何从相关实体获取属性

Core-Data 后台保存性能问题

IOS/Core-Data:添加多对多关系

如何在 Mac 和 iPhone 之间同步 Core-Data 应用程序?

.net core 基于Dapper 的分库分表开源框架(core-data)

SwiftUI - Core-Data - 在这种特殊情况下访问包装的值