当对象具有“描述”时,核心数据不能解决故障。属性? [英] Core Data cannot resolve faults when object has "description" attribute?

查看:140
本文介绍了当对象具有“描述”时,核心数据不能解决故障。属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

代码:

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

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

NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@idascending: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是实体。



以上英语:



初始化一个NSFetchedResultsController来抓取一些数据来为tableview提供动力。



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

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

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

问题/问题:problem指示的行崩溃。



上面的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.438app [22618:20b]< A:0xf7e360> (entity:A; id:0xf35820< x-coredata:// B01FEC86-14D6-4973-BFDB-EDE4AFD24FDC / A / p6> ;; data:{
prop1 = value1;
prop2 = value2;
... etc ...
})

如果对象是类型A,它已经被错误并且在内存中可用,但如果它是B,它是一个错误。



我的理解是, 问题线应该触发故障并从商店获取数据,但这不是发生。我想了解/调试为什么。我试过插入willAccessKey / didAccessKey调用这个。我也试图在获取请求上设置setRelationshipKeyPathsForPrefetching:b。两个都没有工作。



我的假设是,由于我有点滥用NSFetchedRequestController结果,故障引擎沿途混乱,不提取故障至。所以我猜测一个bruteforce方法将是创建一个新的手动获取请求,以在正确的时间获取相关的B对象。但是有更好的方法吗?



编辑



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



问题消失了,当我做了一个新版本的我的模型,重命名描述到别的东西。所有的故障开始工作正如预期。



我不明白,虽然,发生了什么。

解决方案

核心数据编程指南


不鼓励重写描述 - 如果此方法在调试操作期间触发故障,结果可能是不可预测的 - 和initWithEntity :insertIntoManagedObjectContext :.您通常不应覆盖键值编码方法,例如valueForKey:和setValue:forKeyPath:。


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



编程指南在说沮丧时慷慨大方。他们真的是是的,它会打破你的东西。



这个链接还有一个很好的其他方法,如果你覆盖它们将打破你的东西。 / p>

Code:

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

Data model:

A and B are entities. A has mandatory to-one relation to B. B has inverse optional to-many relation to A.

Above in English:

Initialize a NSFetchedResultsController to grab some data to power a tableview. After initial fetch, set the data aside for some processing.

Now, later, I try to do this:

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;
}

Question/problem: the line indicated with "problem" crashes. (EDIT: See below for resolution, but would still like an explanation.)

The NSLog call above yields:

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 ...
})

I.e by the problematic line, if the object was of type A, it has been faulted and is available in memory, but if it is B, it's a fault.

My understanding is that the "problem" line should fire the fault and fetch the data from store, but this is not happening. I would like to understand/debug why. I have tried inserting willAccessKey/didAccessKey calls around this. I also tried to set setRelationshipKeyPathsForPrefetching:"b" on the fetch request. Neither worked.

My hypothesis is that since I'm somewhat abusing the NSFetchedRequestController results, the faulting engine gets confused along the way and doesn't fetch the fault when it's supposed to. So I guess a bruteforce way would be to create a new manual fetch request to fetch the related B object at the right time. But is there a better way?

EDIT:

The problem was that object B had a property "description" that I had defined, but that collides with NSObject's built-in name. Xcode always gave me warnings, but I ignored them because I thought "description" internal property/method is only used for dumping strings to console and the like, not internal processing.

The problem disappeared after I made a new version of my model, renaming "description" to something else. All the faulting started to work as expected.

I don't understand, though, what is going on. Is Core Data using the objects' "description" method for some internal introspection?

解决方案

From Core Data Programming Guide

You are discouraged from overriding description—if this method fires a fault during a debugging operation, the results may be unpredictable—and initWithEntity:insertIntoManagedObjectContext:. You should typically not override the key-value coding methods such as valueForKey: and setValue:forKeyPath:.

-description is a method in NSObject that returns a string representation of your object. In the line NSLog(@"%@", object), -description is used to get the string that you see in the console. Key-value coding will end up using the method to get the property for the description attribute. This causes a whole lot of confusion to Core Data.

The programming guide is being generous when it says "discouraged". They really mean "Yeah, it's going to break your stuff."

That link also has a good list of other methods that will break your stuff if you override them.

这篇关于当对象具有“描述”时,核心数据不能解决故障。属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆