this question exact duplicate of:
i have found couple of answers question, not helpful. trying create app has running stopwatch timer in each cell of tableview, using standard subtitle cells. timer name displayed in textfield , running timer displayed in subtitle. each cell needs display different time format (seconds, minutes, hours, days, months, or years). calculation of time elapsed since timer started done each time timer expires, , result put cell's subtitle. code works fine long 1 timer used. however, if second timer started, running timer in first cell reset zero. believe because saving pointer cell dequeued @ cellforrowatindexpath: , using pointer populate cell when timer expires. violates mvc. however, view controller delegate implements protocol, have return cell when tableview requests it, , can't until timer expires can update subtitle in cell. don't see way without saving pointer cell containing output of running timer. new ios development have written project both programmatically , using storyboard , same results. code view controller below. note item.timertype set view controller segued in storyboard data passed main view controller. part works ok.
thanks help!
// // timeritem.h // lifelogger // // created nelson capes on 9/24/15. // copyright © 2015 nelson capes. rights reserved. // #import <foundation/foundation.h> #import <uikit/uikit.h> @interface timeritem : nsobject @property nsstring *timername; @property nstimeinterval interval; @property nsstring *timeroutput; @property nsdate *starttime; @property nstimer *timer; @property nsinteger timertype; @property uitableviewcell *cell; @end // // nrctimerlisttableviewcontroller.h // lifelogger // // created nelson capes on 9/21/15. // copyright © 2015 nelson capes. rights reserved. // #import <uikit/uikit.h> #import "addtimeritemviewcontroller.h" @interface nrctimerlisttableviewcontroller : uitableviewcontroller <uitabbardelegate, uitableviewdatasource> -(ibaction)listtoadd:(uistoryboardsegue *)segue; @property nstimer *timer; @property(strong) timeritem *item; @property nsdate *starttime; @end // // nrctimerlisttableviewcontroller.m // lifelogger // // created nelson capes on 9/21/15. // copyright © 2015 nelson capes. rights reserved. // #import "nrctimerlisttableviewcontroller.h" #import "timeritem.h" @interface nrctimerlisttableviewcontroller () @property nsmutablearray *items; @end @implementation nrctimerlisttableviewcontroller // control comes here when user hits save button in addtimeritemviewcontroller. // -(ibaction)listtoadd:(uistoryboardsegue *)segue{ if(!self.items){ self.items = [[nsmutablearray alloc]init];} if(self.item != nil) { [self.items addobject:self.item]; [self.tableview reloaddata]; } } -(void)loadinitialdata{ // timeritem object pass onto subsequent view controllers // , add items array } - (void)viewdidload { [super viewdidload]; [self loadinitialdata]; } - (void)didreceivememorywarning { [super didreceivememorywarning]; // dispose of resources can recreated. } #pragma mark - table view data source - (nsinteger)numberofsectionsintableview:(uitableview *)tableview { return 1; } - (nsinteger)tableview:(uitableview *)tableview numberofrowsinsection:(nsinteger)section { return [self.items count];; } - (uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)indexpath { uitableviewcell *cell = [tableview dequeuereusablecellwithidentifier:@"listprototypecell" forindexpath:indexpath]; // configure cell... // first, pointer timer item items array switch (self.item.timertype) { case 0: { nstimeinterval interval = 1; self.item.interval = interval; } break; case 1: { nstimeinterval interval = 60; self.item.interval = interval; } break; case 2: { nstimeinterval interval = 3600; self.item.interval = interval; break; } case 3: { nstimeinterval interval = (3600 * 24); self.item.interval = interval; break; } case 4: { nstimeinterval interval = (36600 * 24 * 30); self.item.interval = interval; break; } case 5: { nstimeinterval interval = (3600 * 24 * 365); self.item.interval = interval; break; } default: break; } self.item.cell = cell; // cell.textlabel.text = self.item.timername; // set start time in item self.item.starttime = [nsdate date]; nstimeinterval startinterval = self.item.interval; self.item.timer = [nstimer scheduledtimerwithtimeinterval:startinterval target:self selector:@selector(timercount:) userinfo:self.item repeats:yes]; [[nsrunloop currentrunloop] addtimer:self.item.timer formode:nsrunloopcommonmodes]; // debug /////////////////////////////////////////////// nslog(@"item %@ timer started", self.item.timername); //////////////////////////////////////////////////////// [self.item.timer fire]; // set textlabel in cell itemname return cell; } -(void)timercount:t { nstimer *timer = t; timeritem *item = timer.userinfo; nslog(@"item %@ timer fired", item.timername); nstimeinterval endinterval = [item.starttime timeintervalsincenow]; endinterval = (-1 * endinterval); switch (item.timertype) { case 0: { int time = round(endinterval); div_t h = div(time, 3600); //seconds total, divided 3600 equals int hours = h.quot; // hours, divided 60 equals div_t m = div(h.rem, 60); // minutes int minutes = m.quot; int seconds = m.rem; // , remainder seconds nsstring *intervalstring = [nsstring stringwithformat:@"%d hours, %d minutes, %d seconds", hours, minutes, seconds]; nsstring *outputstring = [intervalstring stringbyappendingstring:@" ago"]; item.timeroutput = outputstring; } break; case 1: { int time = round(endinterval); div_t h = div(time, 3600); // seconds total, divided 3600 equals int hours = h.quot; // hours, divided 60 equals div_t m = div(h.rem, 60); // minutes int minutes = m.quot; nsstring *intervalstring = [nsstring stringwithformat:@"%d hours, %d minutes", hours, minutes]; nsstring *outputstring = [intervalstring stringbyappendingstring:@" ago"]; item.timeroutput = outputstring; } break; case 2: { int time = round(endinterval); div_t h = div(time, 3600); // seconds total, divided 3600 equals int hours = h.quot; // hours nsstring *intervalstring = [nsstring stringwithformat:@"%d hours", hours]; nsstring *outputstring = [intervalstring stringbyappendingstring:@" ago"]; item.timeroutput = outputstring; } break; case 3: { int time = round(endinterval); div_t h = div(time, 3600); // seconds total, divided 3600 equals int hours = h.quot; // hours, divided 24 equals div_t d =div(h.rem, 24); // days int days = d.quot; nsstring *intervalstring = [nsstring stringwithformat:@"%d days, %d hours", days, hours]; nsstring *outputstring = [intervalstring stringbyappendingstring:@" ago"]; item.timeroutput = outputstring; } break; case 4: { int time = round(endinterval); div_t h = div(time, 3600); // seconds total, divided 3600 equals __unused int hours = h.quot; // hours, divided 24 equals div_t d =div(h.rem, 24); // days int days = d.quot; div_t y = div(d.rem, 12);// divided 12 equals months int months = y.quot; nsstring *intervalstring = [nsstring stringwithformat:@"%d months, %d days", months, days]; nsstring *outputstring = [intervalstring stringbyappendingstring:@" ago"]; item.timeroutput = outputstring; } break; case 5: { int time = round(endinterval); div_t h = div(time, 3600); // seconds total, divided 3600 equals __unused int hours = h.quot; // hours, divided 24 equals div_t d =div(h.rem, 24); // days int days = d.quot; div_t y = div(d.rem, 365);// divided 365 equals years int years = y.quot; nsstring *intervalstring = [nsstring stringwithformat:@"%d years, %d days", years, days]; nsstring *outputstring = [intervalstring stringbyappendingstring:@" ago"]; item.timeroutput = outputstring; } break; } item.cell.textlabel.text = item.timername; item.cell.detailtextlabel.text = item.timeroutput; } /* // override support conditional editing of table view. - (bool)tableview:(uitableview *)tableview caneditrowatindexpath:(nsindexpath *)indexpath { // return no if not want specified item editable. return yes; } */ /* // override support editing table view. - (void)tableview:(uitableview *)tableview commiteditingstyle:(uitableviewcelleditingstyle)editingstyle forrowatindexpath:(nsindexpath *)indexpath { if (editingstyle == uitableviewcelleditingstyledelete) { // delete row data source [tableview deleterowsatindexpaths:@[indexpath] withrowanimation:uitableviewrowanimationfade]; } else if (editingstyle == uitableviewcelleditingstyleinsert) { // create new instance of appropriate class, insert array, , add new row table view } } */ /* // override support rearranging table view. - (void)tableview:(uitableview *)tableview moverowatindexpath:(nsindexpath *)fromindexpath toindexpath:(nsindexpath *)toindexpath { } */ /* // override support conditional rearranging of table view. - (bool)tableview:(uitableview *)tableview canmoverowatindexpath:(nsindexpath *)indexpath { // return no if not want item re-orderable. return yes; } */ #pragma mark - navigation // in storyboard-based application, want little preparation before navigation - (void)prepareforsegue:(uistoryboardsegue *)segue sender:(id)sender { // new view controller using [segue destinationviewcontroller]. // pass selected object new view controller. if([segue.identifier isequaltostring:@"listtoadd"]){ self.item = [[timeritem alloc]init]; addtimeritemviewcontroller *destviewcontroller = segue.destinationviewcontroller; destviewcontroller.timeritem = self.item;} } /* #pragma mark - table view delegate -(void)tableview:(uitableview *)tableview diddeselectrowatindexpath:(nsindexpath *)indexpath{ } */ @end
my code works until scroll tableview after maximum number of cells can fit on screen have been filled. example, on iphone 6 , cell height of 60, can fit 11 rows on screen. of timers in rows fine point. but, if scroll see first cells, unpredictable things happen - of cells have timers reset. noticeable if timers set 1 second. @ longer interval (say, minute), isn't of problem suspect hole still there. code using:
-(void) calculatetimer:(nstimer *)thetimer { self.timeritem = [thetimer userinfo]; // date cell if(self.timeritem.timertype == 0){ [thetimer invalidate]; } // if cell visible , 1 name , type set, put name cell for(nrcitemcell *cell in [self.tableview visiblecells]) { //nslog(@"cell = %@", cell); nsindexpath *ip = [self.tableview indexpathforcell:cell]; nsuinteger row = [[[nrcitemstore sharedstore]allitems] indexofobjectidenticalto:self.timeritem]; nslog(@"ip = %@, row = %lu", ip, (unsigned long)row); if (row == ip.row){ cell.timername.text = self.timeritem.timername; // timertype set timertypetableview controller follows: // 0 - date // 1 - seconds elapsed // 2 - minutes elapsed // 3 - hours elapsed // 4 - days elapsed // 5 - months elapsed // 6 - years elapsed switch (self.timeritem.timertype) { case 0:{ nsdateformatter *dateformatter = [[nsdateformatter alloc] init]; [dateformatter setdatestyle:nsdateformattermediumstyle]; [dateformatter settimestyle:nsdateformatternostyle]; nsdate *date = [nsdate date]; nsstring *formatteddatestring = [dateformatter stringfromdate:date]; cell.timer.text = formatteddatestring; } break; case 1: { nstimeinterval interval = [self.timeritem.starttime timeintervalsincenow]; interval = (-1 * interval); int time = round(interval); div_t h = div(time, 3600); //seconds total, divided 3600 equals int hours = h.quot; // hours, divided 60 equals div_t m = div(h.rem, 60); // minutes int minutes = m.quot; int seconds = m.rem; // , remainder seconds // nslog(@"%d:%d:%d", hours, minutes, seconds); //nsstring *intervalstring = [nsstring stringwithformat:@"%ld", (long)time]; nsstring *intervalstring = [nsstring stringwithformat:@"%d hours, %d minutes, %d seconds", hours, minutes, seconds]; nsstring *outputstring = [intervalstring stringbyappendingstring:@" ago"]; cell.timer.text = outputstring; } break; case 2: { nstimeinterval interval = [self.timeritem.starttime timeintervalsincenow]; interval = (-1 * interval); int time = roundf(interval); div_t h = div(time, 3600); // seconds total, divided 3600 equals int hours = h.quot; // hours, divided 60 equals div_t m = div(h.rem, 60); // minutes int minutes = m.quot; nsstring *intervalstring = [nsstring stringwithformat:@"%d hours, %d minutes", hours, minutes]; nsstring *outputstring = [intervalstring stringbyappendingstring:@" ago"]; cell.timer.text = outputstring; } break; case 3: { nstimeinterval interval = [self.timeritem.starttime timeintervalsincenow]; interval = (-1 * interval); int time = roundf(interval); div_t h = div(time, 3600); // seconds total, divided 3600 equals int hours = h.quot; // hours nsstring *intervalstring = [nsstring stringwithformat:@"%d hours", hours]; nsstring *outputstring = [intervalstring stringbyappendingstring:@" ago"]; cell.timer.text = outputstring; } break; case 4: { nstimeinterval interval = [self.timeritem.starttime timeintervalsincenow]; interval = (-1 * interval); int time = roundf(interval); div_t h = div(time, 3600); // seconds total, divided 3600 equals int hours = h.quot; // hours, divided 24 equals div_t d =div(h.rem, 24); // days int days = d.quot; nsstring *intervalstring = [nsstring stringwithformat:@"%d days, %d hours", days, hours]; nsstring *outputstring = [intervalstring stringbyappendingstring:@" ago"]; cell.timer.text = outputstring; } break; case 5: { nstimeinterval interval = [self.timeritem.starttime timeintervalsincenow]; interval = (-1 * interval); int time = roundf(interval); div_t h = div(time, 3600); // seconds total, divided 3600 equals __unused int hours = h.quot; // hours, divided 24 equals div_t d =div(h.rem, 24); // days int days = d.quot; div_t y = div(d.rem, 12);// divided 12 equals months int months = y.quot; nsstring *intervalstring = [nsstring stringwithformat:@"%d months, %d days", months, days]; nsstring *outputstring = [intervalstring stringbyappendingstring:@" ago"]; cell.timer.text = outputstring; } break; case 6: { nstimeinterval interval = [self.timeritem.starttime timeintervalsincenow]; interval = (-1 * interval); int time = roundf(interval); div_t h = div(time, 3600); // seconds total, divided 3600 equals __unused int hours = h.quot; // hours, divided 24 equals div_t d =div(h.rem, 24); // days int days = d.quot; div_t y = div(d.rem, 365);// divided 365 equals years int years = y.quot; nsstring *intervalstring = [nsstring stringwithformat:@"%d years, %d days", years, days]; nsstring *outputstring = [intervalstring stringbyappendingstring:@" ago"]; cell.timer.text = outputstring; } break; } } } }
Comments
Post a Comment