[英]Filtering a NSArray containing objects with a NSDate field with NSPredicate
我有一個對象數組,每個對象都包含一個稱為date的字段。 我想使用NSPredicate
創建此數組的一個子集,在這里我只拉出屬於某個日期范圍內的那些對象。 這是我正在使用的代碼:
predicate = [NSPredicate predicateWithFormat:@"(date >= %@) AND (date =< %@)", startDate, endDate];
_daysArray = [_cachedDaysArray filteredArrayUsingPredicate:predicate];
我遇到的問題是startDate
和endDate
是同一天,但時間不同。 這是XCode調試器中的變量視圖
如您所見,我在數組中有一個對象,該對象的date
字段等於startDate
,但是您還可以看到_daysArray
在執行過濾器后不包含任何元素。
當日期不是同一天時,這很好用。
任何幫助將不勝感激。
編輯#1
這是評論者要求的predicate
變量的po
:
(lldb) po predicate
date >= CAST(406616400.676014, "NSDate") AND date <= CAST(406702799.677098, "NSDate")
(lldb)
編輯#2
(lldb) po [[_cachedDaysArray firstObject] date]
2013-11-18 05:00:00 +0000
(lldb)
編輯#3
Martin R.通過對startDate
計算方式的評論使我走上了正確的道路。 現在,我已經更改了它,它正在工作。 我正在使用一種方法來計算startDate
。 以前,我使用NSUIntegerMax
指示組件,現在我專門將它們分解:
-(NSDate *)pastDate:(NSInteger)daysPast
{
// Get the appropriate calendar
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *startComponents = [calendar components:(NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitYear|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond) fromDate:[NSDate date]];
[startComponents setHour: 00];
[startComponents setMinute: 00];
[startComponents setSecond: 00];
startComponents.day = startComponents.day - daysPast;
return [calendar dateFromComponents:startComponents];
}
從謂詞的輸出
date >= CAST(406616400.676014, "NSDate") AND date <= CAST(406702799.677098, "NSDate")
可以看到startDate
並非完全是“ 2013-11-20 05:00:00 +0000”(UTC)或“ 2013-11-20 00:00:00”(EST),而是0.676014秒后 。 因此,如果_cachedDaysArray
對象的日期恰好位於2013-11-20的午夜,則它與謂詞不匹配。
似乎startDate
和endDate
的計算與您期望的不完全相同。
在將日期傳遞給謂詞之前,應將日期轉換為不包括時間。 嘗試這個:
-(NSDate*)dateNoTime:(NSDate*)myDate
{
NSDateComponents *comp = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate: myDate];
return [[NSCalendar currentCalendar] dateFromComponents:comp];
}
嘗試這個:
predicate =[NSPredicate predicateWithBlock:^BOOL(TRDay *evaluatedObject, NSDictionary *bindings) {
return evaluatedObject.date.timeIntervalSince1970 >= startDate.timeIntervalSince1970 && evaluatedObject.date.timeIntervalSince1970 <= endDate.timeIntervalSince1970;
}];
我嘗試過這樣的事情:
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components3 = [[NSDateComponents alloc] init];
[components3 setYear:2013];
[components3 setMonth:11];
[components3 setDay:20];
NSDate *startDate = [gregorianCalendar dateFromComponents:components3];
[components3 setHour:23];
[components3 setMinute:59];
[components3 setSecond:59];
NSDate *endDate = [gregorianCalendar dateFromComponents:components3];
[gregorianCalendar release];
NSDictionary* dict = [NSDictionary dictionaryWithObjects:@[startDate] forKeys:@[@"date"]];
NSArray* mainArray = [NSArray arrayWithObjects:dict, nil];
NSPredicate* pred = [NSPredicate predicateWithFormat:@"(date >= %@) AND (date =< %@)", startDate, endDate];
NSArray* filteredArray = [mainArray filteredArrayUsingPredicate:pred];
它按預期工作。 基本上,這意味着您在其他地方有錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.