objective c - How to invalidate contents of UIView to force a redraw? -
i have uiview acts schedule (ipad app written using xcode 4.6, ios 6.2 , storyboards). have 2 (2) uiviews, 1 in top half of window, other in bottom half. there calendar in top half; , grid of times below that. when user taps on day has appointments, drawn on bottom uiview. user can tap day appointments, , old removed, new data drawn on bottom view.
this works great, unless there no appointments day tapped, in case old data remains, rather being somehow deleted. have tried [self setneedsdisplay], since nothing has changed, nothing drawn. there way invalidate contents of uiview force redrawn no data?
update: here code draws appointments:
- (void)drawrect:(cgrect)rect { // load dictionary files plists nsstring *path = [[nsbundle mainbundle] bundlepath]; // nslog(@"\n\npath %@",path); // nsstring *timesfinalpath = [path stringbyappendingpathcomponent:@"startingtimes.plist"]; // starting times nsdictionary *startdict = [nsdictionary dictionarywithcontentsoffile:timesfinalpath]; nsstring *namesfinalpath = [path stringbyappendingpathcomponent:@"technames.plist"]; // 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 have day singletonappointments *sharedinstance = [singletonappointments sharedinstance]; // initialize if(sharedinstance.globalapptlist.count > 0) { for(int = 0; < sharedinstance.globalapptlist.count; i++) { // customer apointments day appointmentinfo *apptobject = [sharedinstance.globalapptlist objectatindex:i]; //nslog(@"apptobject.aapptkey: %@", apptobject.aapptkey); // using apptobject.aapptkey, client's name nspredicate *predicate = ([nspredicate predicatewithformat:@"(aclientkey = %@)", apptobject.aapptkey]); clientinfo = [clientinfo mr_findallwithpredicate: predicate]; nsstring *cliinfo; (clientinfo *cli in clientinfo) { cliinfo = cli.aclientname; // found client name } // settings name drawing const float namefontsize = 14; uifont *hourfont=[uifont systemfontofsize: namefontsize]; // compute duration nsdateformatter *df = [[nsdateformatter alloc] init]; [df setdateformat:@"hh:mm"]; nstimeinterval interval = [apptobject.aendtime timeintervalsincedate:apptobject.astarttime]; int hours = (int)interval / 3600; // integer division hours part int minutes = (interval - (hours*3600)) / 60; // interval minus hours part (in seconds) divided 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 @ 0900... must accomodate that) nsdateformatter *formatter = [[nsdateformatter alloc] init]; [formatter settimezone:[nstimezone timezonewithname:@"gmt"]]; //optionally time zone converstions [formatter setdateformat:@"hh:mm"]; // time shop opens , closes preferencedata *prefdatafound = [preferencedata mr_findfirst]; if(prefdatafound) { // fill times starthour = prefdatafound.ashopopens; endhour = prefdatafound.ashopcloses; } // nslog(@"starthour: %@ endhour: %@",starthour, endhour); // now, first time slot in dictionary nsarray *ts = [startdict allkeysforobject:[nsnumber numberwithint:5]]; // comes 1 entry: 9:00 // clean (remove colon) nsstring *dictvalue = ts[0]; nsstring *cleandictvalue = [dictvalue stringbyreplacingoccurrencesofstring:@":" withstring:@""]; // convert 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 correct column tech name nsnumber *techcolumn = [techdict objectforkey:apptobject.aservicetech]; // nslog(@"\nservicetech: %@, techcolumn: %@", apptobject.aservicetech, techcolumn); // set context cgcontextref context = uigraphicsgetcurrentcontext(); // draw name... (x refers column; y refers time slot) [[uicolor bluecolor] set]; // sets color of customer name nsnumber *timeslot = [startdict objectforkey:stringfromdate]; float correctedslot = [timeslot floatvalue] + gridtimeoffset; // corrected slot info name , rectangle [cliinfo drawatpoint:cgpointmake([techcolumn floatvalue], correctedslot) withfont:hourfont]; // nslog(@"\ntimeslot: %@ adjusted: %@", [timeslot floatvalue], ([timeslot floatvalue] - gridtimeoffset)); // make settings blocking uigraphicsbeginimagecontext(self.bounds.size); // cgcontextsetstrokecolorwithcolor(context, [uicolor blackcolor].cgcolor); // cgcontextsetlinewidth(context, 1.0); // cgcontextref drawing 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 context other appointments draw } }
}
this should handled in callback of view controller of controls bottom view. (if have 1 view controller controls both top , bottom, same applies.) in update method (which should called when day selected, including empty days) there should this.
-(void)update { if (selectedday.events && selectedday.events.count) { // normal update } else { // empty view } }
note if bottom view or has table view, reset data array or set (above referenced selectedday.events
) , call
[_tableview reloaddata];
if have other scheme have empty "manually".
edit
as spokane-dud pointed out, there flaw data source singleton. data has explicitly set nothing when appropriate.
if(appointmentinfo.count > 0) { (appointmentinfo *appt in appointmentinfo) { sharedinstance.globalapptlist = appointmentinfo; // move data sharedinstance } } else { sharedinstance.globalapptlist = nil; }
Comments
Post a Comment