我有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',原因:'无法使用非集合对象执行集合计算。'
我的谓词有什么问题,我需要如何正确指定它?
谢谢!
答案 0 :(得分:2)
首先,要解决您所看到的错误。这是你的谓词:
[NSPredicate predicateWithFormat:@"SUBQUERY(SELF, $x, $x.endYear == endYear - 1 "
"AND $x.endMonth == endMonth AND $x.length = length).@count > 0"]
SUBQUERY
表达式的第一个参数是SUBQUERY
将迭代的集合。因此,您希望SELF
评估为NSArray
或NSSet
。但是,您在子查询谓词中使用关键路径endYear
,endMonth
和length
似乎表明您期望SELF
评估为CalendarPeriod
}。因此,SELF
是一个集合(endYear
,endMonth
和length
是集合的无效密钥路径),或SELF
是{{1} (因此不能用作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
中的替代品在那里收集。或者,如果您将其作为NSFetchRequest
的谓词执行,则可以尝试使用FETCH()
表达式来获取每个CalendarPeriod
对象。
顺便说一下,如果你走这条路,你会看到非常糟糕的表现。这是一个保证O(N 2 ),你可以做得更好。例如,如果您将每个CalendarPeriod
提取到内存中,然后将它们插入由NSDictionary
,endYear
和endMonth
组合键入的length
中,那么你可以把它减少到O(N)时间。