2

编辑感谢马特的帖子,我现在明白我不应该尝试以数组的形式访问“开始”。但是,如果是这种情况,我想知道为什么这段代码似乎在其他地方工作。在我看来,这仍然应该是“一个或另一个”。它应该工作或不应该工作。

原始 我在代码的各个部分使用相同的获取请求来查找最新的游戏:

Game *lastGame = [[[CoreDataAccess managedObjectContext] fetchObjectsForEntityName:@"Game" withPredicate:@"started == started.@max"] anyObject];

'Game' 是一个 NSManagedObject,'started' 是一个日期属性。'started' 在 awakeFromInsert 中为每个对象设置一次。之后就再也没有改变过。游戏从不直接实例化,但它有三个子类。我曾尝试让 Game 既抽象又具体,但对这个问题都没有任何影响。

我正在使用 NSManagedObjectContext 类别来执行提取,如 cocoa with love http://cocoawithlove.com/2008/03/core-data-one-line-fetch.html所示。

我得到的错误如下:

Serious application error.  An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:.  [<__NSDate 0xebb1130> valueForUndefinedKey:]: this class is not key value coding-compliant for the key @max. with userInfo {
    NSTargetObjectUserInfoKey = "2010-11-06 11:16:53 GMT";
    NSUnknownUserInfoKey = "@max";
}

在我看来,谓词可能试图将@max 应用于单个 NSDate,而不是所有游戏中的所有“开始”属性。不过我不确定。我对谓词不是很好,我花了很多时间来做这个。不过,我不明白完全相同的提取如何在不同的地方出现错误。

fetch 不是 NSFetchedResultsController 的一部分,但我在出现错误的类中使用了 fetchedResultsController。例如:

- (void)configureCell:(UITableViewCell*)cell atIndexPath:(NSIndexPath*)indexPath{
Game *game = [self.frc objectAtIndexPath:indexPath];
Game *lastGame = [[[CoreDataAccess managedObjectContext] fetchObjectsForEntityName:@"Game" withPredicate:@"started == started.@max"] anyObject]; // Sometimes we get past this line, sometimes we don't...

NSDateFormatter *format = [[NSDateFormatter alloc] init];
[format setDateFormat:@"EEE, MMM d, yyyy h:mm a"];

if (game != lastGame)
    cell.detailTextLabel.text = [format stringFromDate:game.started];
else
    cell.detailTextLabel.text = @"In Progress";
[format release];
...
}

还有这里:

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
    Game *lastGame = [[[CoreDataAccess managedObjectContext] fetchObjectsForEntityName:@"Game" withPredicate:@"started == started.@max"] anyObject];
    if (lastGame == [frc objectAtIndexPath:indexPath])
        return NO;
    return YES;
}

这种精确的提取在几个地方执行了多次,例如在启动时,但它只在一个类中崩溃。正如我所说,它是间歇性的,但似乎是在我创建一个新的 Game 对象之后的某个时间。游戏是在一个选项卡中创建的,上面的代码来自显示历史的第二个选项卡。

我在这里看到了类似的错误。在这种情况下,通过重新启动计算机解决了问题,这最终让 XCode 意识到该属性已从模型中删除。我已经尝试过了,但我仍然遇到问题。我还尝试删除并重新创建模型中的“开始”属性。我还阅读了核心数据故障排除指南,但也无法在那里找到任何帮助。

4

1 回答 1

1

谓词一次应用于一个源对象。如果您的源对象没有数组属性,则不能使用数组运算符。

在你的情况下,谓词说:

查看给定的“游戏”。如果应用了@max KVC 数组运算符,它自己的“started”属性等于它自己的“started”属性,那么这个谓词将为真。

这不是你想要的。在谓词中使用 KVC 数组运算符的唯一情况是对象的属性数组。例如

获取“games.@max.homeTeamScore > 50”的每个“赛季”(即主队在一场比赛中得分超过 50 的赛季)。这会起作用,因为“Season”上的“games”属性将是一个数组,因此 games.homeTeamScore 也将是一个数组。

但是,单个 Game 上的“started”属性不是数组。你要操作的数组其实是所有游戏的数组,不是游戏的属性。

您可以访问所有游戏数组的唯一扭曲方式是首先获取所有游戏的数组,然后在谓词之外应用数组运算符,然后在谓词内部仅应用相等测试。

即首先获取所有游戏,然后重新获取:

fetchObjectsForEntityName:@"Game" withPredicate:@"started == %@", [allGames valueForKey:@"@max.started"]

但这也不是明智之举。

最终,使用单行 fetch 方法无法正确获取具有最新开始日期的游戏。

您需要创建一个方法的变体,允许您在获取请求上 setSortDescriptors: (按“开始”排序,降序),然后在获取请求上设置 FetchLimit:1 以仅获得第一个结果。

于 2010-11-09T01:14:39.443 回答