I need to format both date and time in a tableView:cellForRowAtIndexPath:
. Since creating an NSDateFormatter
is a fairly heavy operation, I've made them static. Is this the best approach to formatting a date and time on a per-row basis?
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
MyCell*cell = (MyCell*)[self.tableView
dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];
static NSDateFormatter *dateFormatter = nil;
if (!dateFormatter)
{
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[NSLocale currentLocale]];
[dateFormatter setDateStyle:NSDateFormatterLongStyle];
}
cell.dateLabel = [dateFormatter stringFromDate:note.timestamp];
static NSDateFormatter *timeFormatter = nil;
if (!timeFormatter)
{
timeFormatter = [[NSDateFormatter alloc] init];
[timeFormatter setTimeStyle:NSDateFormatterShortStyle];
}
cell.timeLabel = [timeFormatter stringFromDate:note.timestamp];
return cell;
}
I wouldn't use a static variable, because then you'll almost certainly end up with a memory leak. Instead, I would use two NSDateFormatter *
instance variables or properties on that controller object that are instantiated only on demand. When the view unloads or the controller is deallocated, you can then release them.
For example:
@interface MyViewController : UITableViewController {
NSDateFormatter *dateFormatter;
NSDateFormatter *timeFormatter;
}
@end
@implementation MyViewController
- (void)viewDidUnload {
// release date and time formatters, since the view is no longer in memory
[dateFormatter release]; dateFormatter = nil;
[timeFormatter release]; timeFormatter = nil;
[super viewDidUnload];
}
- (void)dealloc {
// release date and time formatters, since this view controller is being
// destroyed
[dateFormatter release]; dateFormatter = nil;
[timeFormatter release]; timeFormatter = nil;
[super dealloc];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// ...
// if a date formatter doesn't exist yet, create it
if (!dateFormatter) {
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[NSLocale currentLocale]];
[dateFormatter setDateStyle:NSDateFormatterLongStyle];
}
cell.dateLabel = [dateFormatter stringFromDate:note.timestamp];
// if a time formatter doesn't exist yet, create it
if (!timeFormatter) {
timeFormatter = [[NSDateFormatter alloc] init];
[timeFormatter setTimeStyle:NSDateFormatterShortStyle];
}
cell.timeLabel = [timeFormatter stringFromDate:note.timestamp];
return cell;
}
@end
I've read in various places that if
you are using NSDateFormatter a lot,
you should set up a static variable,
but in testing this method I found it
used up a lot more memory.
But in your code you don't use static variables for your formatters. Try the following modification:
static NSDateFormatter *dateFormatter = nil;
if (!dateFormatter){
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[NSLocale currentLocale]];
[dateFormatter setDateStyle:NSDateFormatterLongStyle];
}
cell.dateLabel = [dateFormatter stringFromDate:note.timestamp];
// And same approach for timeFormatter
This may not save you memory (as your 2 formatter instances will hand during all run-time period), but creating formatter is heavy operation itself so this approach significantly improves your method performance
You can use this to handle reuse of NSDateFormatter's:
https://github.com/DougFischer/DFDateFormatterFactory#readme
P.S: Since you set only format and locale to your data formatters.