Reputation: 1
I would like to get some suggesstions about the code shown below. The scrolling is kind of slow on iPhone, but not on simulator. What I am trying to do is to show multiple hours and messages on each row and each row may have different numbers of hours and messages.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// message + hours
static NSString *CellIdentifier = @"Cell1";
// others
static NSString *CellIdentifier1 = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UITableViewCell *cell1 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
UILabel *hoursLabel;
UILabel *infoLabel;
UILabel *dayLabel;
switch (indexPath.section) {
case 0:
cell1 = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1] autorelease];
if ([hoursArray count] > 0 && [infoArray count] > 0) {
harray = [self seperateString:[hoursArray objectAtIndex:indexPath.row]];
iarray = [self seperateString:[infoArray objectAtIndex:indexPath.row]];
// check how many hours in an array
int loop = [harray count];
int currentInfoHeight = 0;
int currentHourHeight = 0;
int labelHeight = 0;
for (int i = 0; i < loop ; i++) {
NSString *Text = [[NSString alloc] initWithFormat:@"%@", [harray objectAtIndex:i]];
NSString *Text1 = [[NSString alloc] initWithFormat:@"%@", [iarray objectAtIndex:i]];
UIFont *cellFont = [UIFont systemFontOfSize:hourfontSize];
UIFont *cellFont1 = [UIFont systemFontOfSize:messageFontSize];
CGSize constraintSize = CGSizeMake(180.0f, MAXFLOAT);
CGSize labelSize = [Text sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
CGSize labelSize1 = [Text1 sizeWithFont:cellFont1 constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
/* HourLabel */
hoursLabel =
[[[UILabel alloc]
initWithFrame:
CGRectMake(
70.0 + 2.0 * cell1.indentationWidth,
currentHourHeight + gap,
tableView.bounds.size.width - 70.0 - 4.0 * cell1.indentationWidth,
labelSize.height)]
autorelease];
hoursLabel.text = [NSString stringWithFormat:[harray objectAtIndex:i]];
hoursLabel.backgroundColor = [UIColor clearColor];
hoursLabel.textColor = [UIColor blackColor];
// hoursLabel.shadowColor = [UIColor blackColor];
// hoursLabel.shadowOffset = CGSizeMake(0, 1);
hoursLabel.font = [UIFont systemFontOfSize:hourfontSize];
[cell1.contentView addSubview:hoursLabel];
if (![[iarray objectAtIndex:i] isEqualToString:@"-"]) {
/* infoLabel */
infoLabel =
[[[UILabel alloc]
initWithFrame:
CGRectMake(
70.0 + 2.0 * cell1.indentationWidth,
currentInfoHeight + gap + labelSize.height,
tableView.bounds.size.width - 70.0 - 4.0 * cell1.indentationWidth,
labelSize1.height)]
autorelease];
infoLabel.text = [NSString stringWithFormat:[iarray objectAtIndex:i]];
infoLabel.numberOfLines = 0;
infoLabel.backgroundColor = [UIColor clearColor];
infoLabel.textColor = [UIColor colorWithRed:51.0/255 green:51.0/255.0 blue:51.0/255.0 alpha:1.0];
infoLabel.font = [UIFont systemFontOfSize:messageFontSize];
[cell1.contentView addSubview:infoLabel];
labelHeight = (infoLabel.bounds.size.height);
}
else
{
labelHeight=0;
}
/* store current height of label */
currentHourHeight = (hoursLabel.bounds.size.height) + labelHeight + gap + currentHourHeight;
currentInfoHeight = (hoursLabel.bounds.size.height) + labelHeight + gap + currentInfoHeight;
}
}
/* dayLabel */
dayLabel =
[[[UILabel alloc]
initWithFrame:
CGRectMake(
2.0 * cell1.indentationWidth,
[self tableView:tableView_ heightForRowAtIndexPath:indexPath] / 2.0f - dayFontSize/2 ,
tableView.bounds.size.width -
70.0 - 4.0 * cell1.indentationWidth,
dayFontSize)]
autorelease];
[cell1.contentView addSubview:dayLabel];
/* Configure the properties for the text that are the same on every row */
dayLabel.backgroundColor = [UIColor clearColor];
dayLabel.textColor = [UIColor colorWithRed:207.0/255 green:181.0/255.0 blue:59.0/255.0 alpha:1.0];
dayLabel.font = [UIFont boldSystemFontOfSize:dayFontSize];
/* Draw a line to divide info and message into two sections */
UIView *lineView = [[[UIView alloc] initWithFrame:CGRectMake(79, 0, 1.5, cell1.contentView.bounds.size.height)] autorelease];
lineView.backgroundColor = [self.tableView_ separatorColor];
lineView.autoresizingMask = 0x3f;
[cell1.contentView addSubview:lineView];
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:@"EEE"];
dayLabel.text = [NSString stringWithFormat:[daysArray objectAtIndex:[indexPath row]]];
[cell1 setSelectionStyle:UITableViewCellSelectionStyleNone];
return cell1;
case 1:
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = @"View information for this location";
cell.textLabel.font = [UIFont systemFontOfSize:16];
cell.textLabel.textAlignment = UITextAlignmentCenter;
return cell;
case 2:
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = @"Show building on campus map";
cell.textLabel.font = [UIFont systemFontOfSize:16];
cell.textLabel.textAlignment = UITextAlignmentCenter;
return cell;
case 3:
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = @"Direction to building";
cell.textLabel.font = [UIFont systemFontOfSize:16];
cell.textLabel.textAlignment = UITextAlignmentCenter;
return cell;
default:
break;
}
return cell;
}
Upvotes: 0
Views: 1146
Reputation: 90117
You are allocating a NSDateFormatter for each cell. In my experience NSDateFormatter allocation and configuration are some of the most expensive calls available. They take significant amount of time.
Make that NSDateFormatter an instance variable so you have to allocate and configure it exactly one time.
you are not reusing your cells. If you don't reuse your cells your performance will suffer. The pattern to reuse is something like this:
.
- (NSDateFormatter *)weekDayDateFormatter {
if (!myWeekDayDateFormatter) {
myWeekDayDateFormatter = [[NSDateFormatter alloc] init];
[myWeekDayDateFormatter setDateFormat:@"EEE"];
}
return myWeekDayDateFormatter;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSInteger secondLabelTag = 1001;
static NSInteger imageViewTag = 1002;
static NSString *CellIdentifier1 = @"Cell1";
static NSString *CellIdentifier2 = @"Cell2";
UITableViewCell *cell = nil;
switch (indexPath.section) {
case 0: {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier1];
// allocate subviews and configure properties that never change
UILabel *secondLabel = [[UILabel alloc] initWithFrame:CGRectZero];
secondLabel.tag = secondLabelTag;
secondLabel.textColor = [UIColor orangeColor];
[cell.contentView addSubview:secondLabel];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
imageView.tag = imageViewTag;
imageView.contentMode = UIViewContentModeScaleAspectFill;
[cell.contentView addSubview:imageView];
}
// Whatever happened before you have a valid cell here
UILabel *secondLabel = (UILabel *)[cell.contentView viewWithTag:secondLabelTag];
UIImageView *imageView = (UIImageView *)[cell.contentView viewWithTag:imageViewTag];
secondLabel.text = [self.weekDayDateFormatter stringFromDate:[dataSource objectAtIndex:indexPath.row]];
imageView.image = [dataSource objectAtIndex:indexPath.row];
break;
}
case 1: {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier2];
// configure properties that never change between cells
cell.textLabel.textColor = [UIColor greenColor];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
// configure properties that are different between cells
cell.textLabel.text = [dataSource objectAtIndex:indexPath.row];
cell.textLabel.backgroundColor = [dataSource objectAtIndex:indexPath.row];
break;
}
}
The code in the tableView:cellForRowAtIndexPath:
parts that are called every time should execute as fast as possible. During scrolling this method is called for every single cell.
Upvotes: 1
Reputation: 8180
I guess, the performance isn't lost here, but in -cellForRowAtIndexPath:
Do you use – prepareForReuse
/ – dequeueReusableCellWithIdentifier:
?
Upvotes: 0