对象具有“描述”属性时,核心数据无法解决错误?

问题描述:

代码:对象具有“描述”属性时,核心数据无法解决错误?

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 

NSEntityDescription *entity = [NSEntityDescription entityForName:@"A" 
              inManagedObjectContext:moc]; 
[fetchRequest setEntity:entity]; 

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"id" ascending:NO]; 
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; 
[fetchRequest setSortDescriptors:sortDescriptors]; 
[sortDescriptors release]; 
[sortDescriptor release]; 

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"somePredicate", someObject]; 
[fetchRequest setPredicate:predicate]; 

frc = [[NSFetchedResultsController alloc] 
     initWithFetchRequest:fetchRequest 
     managedObjectContext:moc 
     sectionNameKeyPath:@"recency" 
     cacheName:@"frc"]; 
[fetchRequest release]; 

frc.delegate = self; 

NSError *error; 
BOOL success = [frc performFetch:&error]; 
if (!success) { 
    NSLog(@"error: %@", error); 
} 

for (A *a in [frc fetchedObjects]) {   
    [someMutableArray addObject:a.b]; 
    [someMutableArray addObject:a]; 
} 

数据模型:

A和B是实体。 A具有强制性的一对一关系B. B具有逆可选的一对多关系A.

以上英语:

初始化NSFetchedResultsController抓一些数据来驱动一个实现代码如下。初次抓取后,将数据放在一边进行一些处理。

现在,以后,我尝试这样做:

id object = [someMutableArray objectAtIndex:someIndex]; 
NSLog(@"%@", object); 

if ([object isMemberOfClass:[B class]]) { 
    someVar = object.propertyFromB; // problem 
} else if ([object isMemberOfClass:[A class]]) { 
    someVar = object.propertyFromA; 
} 

问题/问题:符合 “问题” 崩溃指示。 (编辑:下面参见分辨率,但仍然希望的解释。)

的NSLog的呼叫以上的产率:

2010-01-30 14:47:14.433 app[22618:20b] <B: 0xf7f750> (entity: B; id: 0xf7ba70 <x-coredata://B01FEC86-14D6-4973-BFDB-EDE4AFD24FDC/B/p4> ; data: <fault>) 
2010-01-30 14:47:14.438 app[22618:20b] <A: 0xf7e360> (entity: A; id: 0xf35820 <x-coredata://B01FEC86-14D6-4973-BFDB-EDE4AFD24FDC/A/p6> ; data: { 
    prop1 = value1; 
    prop2 = value2; 
    ... etc ... 
}) 

Ie的有问题的线路,如果对象是A型的,它一直存在故障并在内存中可用,但如果是B,则是故障。

我的理解是,“问题”行应该触发故障并从存储中获取数据,但这不会发生。我想了解/调试原因。我曾尝试在此附加插入willAccessKey/didAccessKey调用。我也尝试在提取请求上设置setRelationshipKeyPathsForPrefetching:“b”。都没有工作。

我的假设是,由于我有点滥用NSFetchedRequestController结果,故障引擎一路上感到困惑,并且在应该的时候没有获取错误。所以我猜bruteforce的方法是创建一个新的手动抓取请求来在适当的时候抓取相关的B对象。但是有更好的方法吗?

编辑:

问题是,对象B有一个属性“描述”,我已经确定,但与NSObject中的内置名称冲突。 Xcode总是给我警告,但我忽略了它们,因为我认为“description”内部属性​​/方法仅用于将字符串转储到控制台等,而不是内部处理。

在我制作新模型后,问题消失,将“描述”重命名为其他内容。所有的错误都开始按预期工作。

虽然我不明白发生了什么事。核心数据是否使用对象的“描述”方法进行一些内部自省?

Core Data Programming Guide

您正在从重写描述-如果此方法的调试操作期间触发一个故障时,结果可能是不可预知的,并且initWithEntity气馁:insertIntoManagedObjectContext :.您通常不应覆盖键值编码方法,如valueForKey:和setValue:forKeyPath :.

-description是NSObject中的一个方法,它返回对象的字符串表示形式。在行NSLog(@"%@", object)中,-description用于获取您在控制台中看到的字符串。键值编码将最终使用该方法来获取描述属性的属性。这对Core Data造成了很大的困惑。

当编程指南中显示“不鼓励”时,编程指南就显得很慷慨。他们真的是说“是的,它会打破你的东西。”

该链接还有一个很好的其他方法列表,如果你重写它们,它们会打破你的东西。

+0

这一切都是有道理的,我通常会尽量避免重写这种“众所周知”的方法。我没有意识到“描述”有多敏感。 – Jaanus 2010-01-31 06:55:05

您需要将描述视为保留字。这是你遇到的问题。当您尝试拥有名为description的属性时,您应该收到警告。

+0

我确实收到警告。我以为我会忽略它,因为当我开始创建对象时,在开始时我没有任何问题。原来,这是一个坏主意:) – Jaanus 2010-01-31 07:51:51

+1

是的,忽略警告是一个坏主意。每个开发者都应该争取免费构建警告!甚至可能会将“警告”设置为错误。 – Hunter 2010-01-31 18:33:10

+0

对具有“描述”属性的实体进行建模是否有最佳做法?人们倾向于称之为“desc”还是什么? – Hugh 2010-07-28 12:10:44

对于自定义描述,欢迎您从NSObject协议覆盖-(NSString *)debugDescription。 来自Apple的文档:

NSObject通过调用描述方法来实现此方法。 因此,默认情况下,对象的调试描述与其描述的 相同。但是,如果要将 解耦,可以覆盖debugDescription。