Reputation: 1479
Please see edit below
I'm trying to update the text in a label in a UITableViewCell
in real time to reflect the elapsed time since the cell was selected via didSelectRowAtIndexPath
.
The symptom of the problem is that the label remains blank.
Here is the code in my updateTime
method:
-(void)updateTime
{
//Which calendar
NSCalendar *calendar = [NSCalendar currentCalendar];
//Gets the componentized interval from the most recent time an activity was tapped until now
NSDateComponents *components= [calendar components:NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit fromDate:currentTimedActivity.startTime toDate:[NSDate date] options:0];
NSInteger hours = [components hour];
NSInteger minutes = [components minute];
NSInteger seconds =[components second];
//
if(!seconds)
{
[timer invalidate];
}
//Converts the components to a string and displays it in the duration label
cellLabelTempText = [NSString stringWithFormat:@"%02i:%02i:%02i",hours,minutes,seconds];
self.durationLabel.text = cellLabelTempText;
NSLog(@"The label should be reading %02i:%02i:%02i",hours,minutes,seconds);
NSLog(@"cellLabelTempText is reading %@",cellLabelTempText);
NSLog(@"The durationLabel should read the same, as they are equal.");
NSLog(@"The durationLabel is actually showing %@",self.durationLabel.text);
[self.myTableView reloadData];
}
My NSLog instructions yield the following:
2014-03-12 14:48:57.433 WMDGx[69802:a0b] The label should be reading 00:00:00
2014-03-12 14:48:57.434 WMDGx[69802:a0b] cellLabelTempText is reading 00:00:00
2014-03-12 14:48:57.435 WMDGx[69802:a0b] The durationLabel should read the same, as they are equal.
2014-03-12 14:48:57.435 WMDGx[69802:a0b] The durationLabel is actually showing (null)
2014-03-12 14:48:57.933 WMDGx[69802:a0b] The label should be reading 00:00:01
2014-03-12 14:48:57.934 WMDGx[69802:a0b] cellLabelTempText is reading 00:00:01
2014-03-12 14:48:57.934 WMDGx[69802:a0b] The durationLabel should read the same, as they are equal.
2014-03-12 14:48:57.935 WMDGx[69802:a0b] The durationLabel is actually showing (null)
2014-03-12 14:48:58.933 WMDGx[69802:a0b] The label should be reading 00:00:02
2014-03-12 14:48:58.934 WMDGx[69802:a0b] cellLabelTempText is reading 00:00:02
2014-03-12 14:48:58.934 WMDGx[69802:a0b] The durationLabel should read the same, as they are equal.
2014-03-12 14:48:58.935 WMDGx[69802:a0b] The durationLabel is actually showing (null)
2014-03-12 14:48:59.933 WMDGx[69802:a0b] The label should be reading 00:00:03
2014-03-12 14:48:59.934 WMDGx[69802:a0b] cellLabelTempText is reading 00:00:03
2014-03-12 14:48:59.934 WMDGx[69802:a0b] The durationLabel should read the same, as they are equal.
2014-03-12 14:48:59.934 WMDGx[69802:a0b] The durationLabel is actually showing (null)
2014-03-12 14:49:00.933 WMDGx[69802:a0b] The label should be reading 00:00:04
2014-03-12 14:49:00.933 WMDGx[69802:a0b] cellLabelTempText is reading 00:00:04
2014-03-12 14:49:00.934 WMDGx[69802:a0b] The durationLabel should read the same, as they are equal.
2014-03-12 14:49:00.934 WMDGx[69802:a0b] The durationLabel is actually showing (null)
I'm stumped because the temporary string cellLabelTempText
is updating correctly, and self.durationLabel.text
is equal to cellLabelTempText
, yet registers as (null)
in the log.
All help much appreciated!
Edit per @rmaddy's suggestion in comments below (please read):
Since my self.durationLabel
is showing nil
, I tried connecting to an IBOutlet, but get this error:
... /WMDGx/MainStoryboard.storyboard: Couldn't compile connection: <IBCocoaTouchOutletConnection:0x7ff6a28f8560 <IBProxyObject: 0x7ff6a28f55e0> => durationLabel => <IBUILabel: 0x7ff6a28f34a0>>
This gives a good indication about where the problem lies, but if the whole thing depends on an IBOutlet, and I can't hook it up to one, where do I go from here?
Thanks!
Upvotes: 0
Views: 709
Reputation: 5953
Your issue is that you don't have a single durationLabel; you have as many as you have cells in your table. (The error specifically is trying to connect a tableCell prototype to a specific label). I'd suggest subclassing UITableviewCell, adding a durationLabel label and property (which can be linked to a prototype cell), and putting this timer code inside that subclass.
Something like this:
In your tableViewController:
//At the top:
#import "PTCell.h"
//replace didSelectRowAtIndexPath:
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
PTCell * cell = (PTCell *)[tableView cellForRowAtIndexPath:indexPath];
[cell startTimer];
}
PTCell.h:
#import <UIKit/UIKit.h>
@interface PTCell : UITableViewCell;
@property (strong, nonatomic) IBOutlet UILabel *durationLabel;
@property (nonatomic, strong) NSDate * startTime;
@property (nonatomic, strong) NSTimer * timer;
-(void) startTimer;
-(void) stopTimer;
@end
PTCell.m:
#import "PTCell.h"
@implementation PTCell
-(void)updateTime {
//Which calendar
NSCalendar *calendar = [NSCalendar currentCalendar];
//Gets the componentized interval from the most recent time an activity was tapped until now
NSDateComponents *components= [calendar components:NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit fromDate:self.startTime toDate:[NSDate date] options:0];
NSInteger hours = [components hour];
NSInteger minutes = [components minute];
NSInteger seconds =[components second];
//
if(!seconds)
{
[self.timer invalidate];
}
//Converts the components to a string and displays it in the duration label
NSString * cellLabelTempText = [NSString stringWithFormat:@"%02i:%02i:%02i",hours,minutes,seconds];
self.durationLabel.text = cellLabelTempText;
NSLog(@"The label should be reading %02i:%02i:%02i",hours,minutes,seconds);
NSLog(@"cellLabelTempText is reading %@",cellLabelTempText);
NSLog(@"The durationLabel should read the same, as they are equal.");
NSLog(@"The durationLabel is actually showing %@",self.durationLabel.text);
}
-(void) startTimer {
[self stopTimer];
self.startTime = [NSDate date];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime) userInfo:nil repeats:YES];
}
-(void) stopTimer {
[self.timer invalidate];
self.timer = nil;
}
@end
Upvotes: 2