I have an NSDate I want to search for in my predicate. However, the timing may not be 2009-12-06 00:00:00 +0000
but may look more like 2009-12-06 3:05:90 +0000
. So how can I search for any date that fits within the bounds of that day (24 hours).
Edit:
These are the related methods to the crash:
Crash is happening in this method
related to the Calendar's API framework
- (void) reactToTouch:(UITouch*)touch down:(BOOL)down
{
...
if ([marks count] > 0) {
if([[marks objectAtIndex: row * 7 + column] boolValue])
[self.selectedImageView addSubview:self.dot];
else
[self.dot removeFromSuperview];
}else{
[self.dot removeFromSuperview];
}
...
}
This graph sets the graph's date and dots for the date if there is data for that date
- (NSArray*)calendarMonthView:(TKCalendarMonthView *)monthView marksFromDate:(NSDate *)startDate toDate:(NSDate *)lastDate {
NSLog(@"calendarMonthView marksFromDate toDate");
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Session" inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
[request setResultType:NSDictionaryResultType];
[request setReturnsDistinctResults:YES];
[request setPropertiesToFetch :[NSArray arrayWithObject:@"timeStamp"]];
NSError *error;
NSArray *objects = [managedObjectContext executeFetchRequest:request error:&error];
NSArray *tempData = [objects valueForKey:@"timeStamp"];
NSMutableArray * data1 = [NSMutableArray array];
NSCalendar * gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
[gregorian setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];
NSUInteger flags = ( NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit );
NSDateFormatter* formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss Z"];
[formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];
[tempData enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSDate * date = [gregorian dateFromComponents:[gregorian components:flags fromDate:obj]];
[data1 addObject:[formatter stringFromDate:date]];
}];
self.data = data1;
// Initialise empty marks array, this will be populated with TRUE/FALSE in order for each day a marker should be placed on.
NSMutableArray *marks = [NSMutableArray array];
// Initialise calendar to current type and set the timezone to never have daylight saving
NSCalendar *cal = [NSCalendar currentCalendar];
[cal setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDateComponents *comp = [cal components:(NSMonthCalendarUnit | NSMinuteCalendarUnit | NSYearCalendarUnit | NSDayCalendarUnit | NSWeekdayCalendarUnit | NSHourCalendarUnit | NSSecondCalendarUnit) fromDate:startDate];
NSDate *d = [cal dateFromComponents:comp];
// Init offset components to increment days in the loop by one each time
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setDay:1];
// for each date between start date and end date check if they exist in the data array
while (YES) {
// Is the date beyond the last date? If so, exit the loop.
// NSOrderedDescending = the left value is greater than the right
if ([d compare:lastDate] == NSOrderedDescending) {
开发者_如何学Python break;
}
// If the date is in the data array, add it to the marks array, else don't
if ([data containsObject:[d description]]) {
[marks addObject:[NSNumber numberWithBool:YES]];
} else {
[marks addObject:[NSNumber numberWithBool:NO]];
}
// Increment day using offset components (ie, 1 day in this instance)
d = [cal dateByAddingComponents:offsetComponents toDate:d options:0];
}
[offsetComponents release];
[request release];
return [NSArray arrayWithArray:marks];
}
And finally, this is the method we came up with, that pushes to the detail view when a date is selected:
- (void)calendarMonthView:(TKCalendarMonthView *)monthView didSelectDate:(NSDate *)d {
NSLog(@"calendarMonthView didSelectDate");
NSDateFormatter* formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"];
[formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];
NSString * dateString = [formatter stringFromDate:d];
if ( [data containsObject:dateString] )
{
NSDate * searchDate = [formatter dateFromString:dateString];
NSCalendar * calendar1 = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents * dateComponents = [[[NSDateComponents alloc] init] autorelease];
[dateComponents setDay:1];
NSDate * searchDateEnd = [calendar1 dateByAddingComponents:dateComponents toDate:searchDate options:0];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Session" inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSPredicate * predicate1 = [NSPredicate predicateWithFormat:@"timeStamp >= %@ AND timeStamp < %@", searchDate, searchDateEnd];
[request setPredicate: predicate1];
[request setFetchBatchSize:20];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
NSError *error = nil;
NSArray *array = [managedObjectContext executeFetchRequest:request error:&error];
NSLog(@"xxx array: %@", array);
SessionViewController *sessionViewController = [[SessionViewController alloc] initWithNibName:@"SessionViewController" bundle:nil];
self.selectedSession = (Session *)[array objectAtIndex:0];
sessionViewController.selectedSession = self.selectedSession;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"MMM d, y"];
NSString *dateString = [dateFormatter stringFromDate:selectedSession.timeStamp];
sessionViewController.title = dateString;
sessionViewController.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:sessionViewController animated:YES];
[sessionViewController release];
[dateFormatter release];
[sortDescriptor release];
[request release];
[sortDescriptors release];
}
}
Edit:
When I log the the dates,
The rawDate is straight session.timeStamp
and dateString has a date formatter of [dateFormatter setDateFormat:@"eeee, MMM d, y"];
2011-06-27 20:13:44.936 Curl[18714:707] dateString: Monday, Jun 27, 2011
2011-06-27 20:13:44.941 Curl[18714:707] rawString: 2011-06-27 07:05:01 +0000
2011-06-27 20:13:44.961 Curl[18714:707] dateString: Thursday, Jun 23, 2011
2011-06-27 20:13:44.965 Curl[18714:707] rawString: 2011-06-23 08:12:49 +0000
2011-06-27 20:13:44.977 Curl[18714:707] dateString: Wednesday, Jun 22, 2011
2011-06-27 20:13:44.983 Curl[18714:707] rawString: 2011-06-22 21:23:08 +0000
2011-06-27 20:13:44.993 Curl[18714:707] dateString: Tuesday, Jun 21, 2011
2011-06-27 20:13:44.997 Curl[18714:707] rawString: 2011-06-22 03:23:51 +0000
2011-06-27 20:13:45.007 Curl[18714:707] dateString: Monday, Jun 20, 2011
2011-06-27 20:13:45.011 Curl[18714:707] rawString: 2011-06-21 01:03:53 +0000
2011-06-27 20:13:45.020 Curl[18714:707] dateString: Friday, Jun 17, 2011
2011-06-27 20:13:45.024 Curl[18714:707] rawString: 2011-06-18 01:03:53 +0000
Adding a day to searchDate
can be done with NSDateComponents
using the code below.
NSCalendar * calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents * dateComponents = [[[NSDateComponents alloc] init] autorelease];
[dateComponents setDay:1];
NSDate * searchDateEnd = [calendar dateByAddingComponents:dateComponents
toDate:searchDate
options:0];
Add this after you get the searchDate
.
You might also want to change the predicate to
NSPredicate * predicate1 = [NSPredicate predicateWithFormat:@"timeStamp >= %@ AND timeStamp < %@", searchDate, searchDateEnd];
Don't check for equality with the upper limit.
Edit
If you look at the code below,
if ([marks count] > 0) {
if([[marks objectAtIndex: row * 7 + column] boolValue])
[self.selectedImageView addSubview:self.dot];
else
[self.dot removeFromSuperview];
}
You don't have checks on the index and since this seems to represent values pertaining to days in a month, I would suggest you check if there is a valid value.
int size = [marks count];
if ((size > 0) && ((row * 7 + column) < size)) {
if([[marks objectAtIndex: row * 7 + column] boolValue])
[self.selectedImageView addSubview:self.dot];
else
[self.dot removeFromSuperview];
}
精彩评论