I have a UIView that acts like a schedule (iPad app written using XCode 4.6, iOS 6.2 and Storyboards). I actually have two (2) UIVIews, one in the top half of the window, the other in the bottom half. There is a calendar in the top half; and a grid of times below that. When the user taps on a day that has appointments, they are drawn on the bottom UIView. The user can tap any day with appointments, and the old is removed, the new data is drawn on the bottom view.
This works great, unless there are no appointments for that day that was tapped, in which case the old data remains, rather than being somehow deleted. I have tried [self setNeedsDisplay], but since nothing has changed, nothing is drawn. Is there a way to invalidate the contents of the UIView to force it to be redrawn with no data?
UPDATE: here is the code that draws the appointments:
- (void)drawRect:(CGRect)rect {
// load dictionary files from plists
NSString *path = [[NSBundle mainBundle] bundlePath];
// NSLog(@"\n\npath %@",path);
//
NSString *timesFinalPath = [path stringByAppendingPathComponent:@"startingTimes.plist"]; // do starting times
NSDictionary *startDict = [NSDictionary dictionaryWithContentsOfFile:timesFinalPath];
NSString *namesFinalPath = [path stringByAppendingPathComponent:@"techNames.plist"]; // do tech names
NSDictionary *techDict = [NSDictionary dictionaryWithContentsOfFile:namesFinalPath];
// NSLog(@"\nPath: %@\ntechDict.count: %d\nstartDict.count %d", path, techDict.count, startDict.count);
// NSLog(@"nbr of recognizers: %lu", (unsigned long)self.gestureRecognizers.count);
// find out how many appointments we have for this day
SingletonAppointments *sharedInstance = [SingletonAppointments sharedInstance]; // initialize
if(sharedInstance.globalApptList.count > 0) {
for(int i = 0; i < sharedInstance.globalApptList.count; i++) { // get customer apointments for this day
AppointmentInfo *apptObject = [sharedInstance.globalApptList objectAtIndex:i];
//NSLog(@"apptObject.aApptKey: %@", apptObject.aApptKey);
// using apptObject.aApptKey, get the client's name
NSPredicate *predicate = ([NSPredicate predicateWithFormat:@"(aClientKey = %@)", apptObject.aApptKey]);
clientInfo = [ClientInfo MR_findAllWithPredicate: predicate];
NSString *cliInfo;
for (ClientInfo *cli in clientInfo) {
cliInfo = cli.aClientName; // found client name
}
// settings for name drawing
const float nameFontSize = 14;
UIFont *hourfont=[UIFont systemFontOfSize: nameFontSize];
// now compute the duration
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"HH:mm"];
NSTimeInterval interval = [apptObject.aEndTime timeIntervalSinceDate:apptObject.aStartTime];
int hours = (int)interval / 3600; // integer division to get the hours part
int minutes = (interval - (hours*3600)) / 60; // interval minus hours part (in seconds) divided by 60 yields minutes
// NSString *duration = [NSString stringWithFormat:@"%d:%02d", hours, minutes];
// localize time
NSDate *sTime = [self localizeDate: apptObject.aStartTime];
// NSDate *eTime = [self localizeDate: apptObject.aEndTime];
// NSLog(@"\n\nsTime: %@ eTime: %@", sTime, eTime);
// NSLog(@"\nlocalized sTime: %@\nlocalized eTime %@", sTime, eTime);
// determine time slot (dictiionary starts at 0900... must accomodate for that)
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]]; //Optionally for time zone converstions
[formatter setDateFormat:@"HH:mm"];
// get time shop opens and closes
PreferenceData *prefDataFound = [PreferenceData MR_findFirst];
if(prefDataFound) { // fill the times
startHour = prefDataFound.aShopOpens;
endHour = prefDataFound.aShopCloses;
}
// NSLog(@"startHour: %@ endHour: %@",startHour, endHour);
// now, get first time slot in dictionary
NSArray *ts = [startDict allKeysForObject:[NSNumber numberWithInt:5]]; // comes back with one entry: 9:00
// clean it (remove colon)
NSString *dictValue = ts[0];
NSString *cleanDictValue = [dictValue stringByReplacingOccurrencesOfString:@":" withString:@""];
// convert to int
int dictStartTime = [cleanDictValue intValue];
int intStartHour = [startHour intValue];
// compute gridTimeOffset
float gridTimeOffset = dictStartTime - intStartHour;
NSString *stringFromDate = [formatter stringFromDate:sTime];
// NSLog(@"\n\nstringFromDate: %@",stringFromDate);
// NSLog(@"\nserviceTech: %@", apptObject.aServiceTech);
// find the correct column by tech name
NSNumber *techColumn = [techDict objectForKey:apptObject.aServiceTech];
// NSLog(@"\nserviceTech: %@, techColumn: %@", apptObject.aServiceTech, techColumn);
// set the context
CGContextRef context = UIGraphicsGetCurrentContext();
// draw the name... (x refers to column; y refers to time slot)
[[UIColor blueColor] set]; // sets color of customer name
NSNumber *timeSlot = [startDict objectForKey:stringFromDate];
float correctedSlot = [timeSlot floatValue] + gridTimeOffset; // corrected slot info for name and rectangle
[cliInfo drawAtPoint:CGPointMake([techColumn floatValue], correctedSlot) withFont:hourfont];
// NSLog(@"\ntimeSlot: %@ adjusted: %@", [timeSlot floatValue], ([timeSlot floatValue] - gridTimeOffset));
// make some settings for the blocking
UIGraphicsBeginImageContext(self.bounds.size);
// CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
// CGContextSetLineWidth(context, 1.0);
// get the CGContextRef for drawing the rectangle
CGContextSetFillColorWithColor(context, [[[UIColor grayColor] colorWithAlphaComponent: 0.3] CGColor]);
// NSNumber *startPos = [startDict objectForKey:stringFromDate];
int shadeHeight = ((hours * 4) + (minutes / 15)) * 25; // compute starting y value
// CGContextFillRect(context, CGRectMake([techColumn floatValue], [startPos floatValue], 218, (float)shadeHeight));
CGContextFillRect(context, CGRectMake([techColumn floatValue], correctedSlot, 218, (float)shadeHeight));
UIGraphicsEndImageContext(); // end the context so the other appointments will draw
}
}
}