0

我有一个NSArray日历周期,其中包含NSManagedObjects并建模,如此屏幕截图所示:

核心数据模型

具有以下示例内容:

endMonth = 9;
endYear = 2012;
length = 3;
...

我正在尝试做的事情:

我正在尝试构建一个谓词,该谓词仅返回存在一年前等效期间的那些日历期间。示例:仅当数组中2012, 9, 3有周期时,才返回周期(年、月、长度)作为结果。2011, 9, 3谓词需要将每个日历周期与数组中的每个日历周期进行比较。

这是我尝试过的谓词:

predicate = [NSPredicate predicateWithFormat:
       @"SUBQUERY(SELF, $x, $x.endYear == endYear - 1 "
        "AND $x.endMonth == endMonth AND $x.length = length).@count > 0"];

问题:

但是,使用此谓词运行我的应用程序会导致运行时崩溃并显示错误消息: NSInternalInconsistencyException',原因:'无法使用非集合对象执行集合评估。'

我的谓词有什么问题,我需要如何正确指定它?

谢谢!

4

1 回答 1

2

首先,解决您看到的错误。这是你的谓词:

[NSPredicate predicateWithFormat:@"SUBQUERY(SELF, $x, $x.endYear == endYear - 1 "
    "AND $x.endMonth == endMonth AND $x.length = length).@count > 0"]

表达式的第一个参数是将迭代SUBQUERY的集合。SUBQUERY因此,您期望SELF评估为 anNSArray或 an NSSet。但是,您在子查询谓词中使用 keypaths endYearendMonthlength似乎表明您希望SELF评估为CalendarPeriod. 因此,要么SELF是一个集合(并且endYear,endMonthlength是集合的无效键路径),要么SELF是一个CalendarPeriod(因此不能用作SUBQUERY' 的集合。根据您的错误,它似乎是后者。

如果我们要写出你的问题(不使用NSPredicate),我们可能会得到这样的结果:

NSArray *calendarPeriods = ...;
for (CalendarPeriod *period in calendarPeriods) {
  for (CalendarPeriod *otherPeriod in calendarPeriods) {
    if ([otherPeriod endYear] == [period endYear] - 1 && [otherPeriod endMonth] == [period endMonth] && [otherPeriod length] == [period length]) {
      return YES;
    }
  }
}
return NO;

那么,如何复制这个...

您最初的尝试似乎相当不错。我认为唯一需要做的改变是,你应该使用 , 而不是SELF作为 的第一个参数,而SUBQUERY应该使用, 和集合%@中的替代品。calendarPeriods或者,如果您将 this 作为 a 的谓词执行NSFetchRequest,您可以尝试使用FETCH()表达式来获取每个CalendarPeriod对象。

顺便说一句,如果你走这条路,你会看到非常糟糕的表现。这是一个有保证的 O(N 2 ),你可以做得更好。例如,如果您将 every 提取CalendarPeriod到内存中,然后将它们插入到由、 和NSDictionary的组合键控中endYear,那么您可以将其减少到 O(N) 时间。endMonthlength

于 2012-11-04T21:28:48.530 回答