Question

I have the following code to add a border colour and drop shadow to the background of my UITableViewCell. My problem is that this code causes a huge lag on the tableView itself.

Please can you tell me how I can optimise my code, preventing the lag of the UITableView?

if ([cell viewWithTag:012] == nil && comment.isReply == NO) {
    UIImageView *iv = [[[UIImageView alloc] initWithFrame:frame] autorelease];
    [iv setImage:[UIImage imageNamed:@"paper"]];
    [iv setTag:012];
    [cell insertSubview:iv atIndex:0];

    [iv.layer setBorderWidth:1.0];
    [iv.layer setBorderColor:[[UIColor whiteColor] CGColor]];

    [iv.layer setShadowColor:[[UIColor blackColor] CGColor]];
    [iv.layer setShadowOffset:CGSizeMake(0, 1)];
    [iv.layer setShadowOpacity:0.75];

}

else if ([cell viewWithTag:012] == nil && comment.isReply == YES) {

    frame.origin.x += 35;

    UIImageView *iv = [[[UIImageView alloc] initWithFrame:frame] autorelease];
    [iv setImage:[UIImage imageNamed:@"paper"]];
    [iv setTag:012];
    [cell insertSubview:iv atIndex:0];

    UIImage *arrow = [UIImage imageNamed:@"arrow"];
    UIImageView *ivs = [[[UIImageView alloc] initWithFrame:CGRectMake(-12, ([cell frame].size.width / 2) + ([arrow size].width/2) , arrow.size.width, arrow.size.height)] autorelease];
    [cell addSubview:ivs];

    [iv.layer setBorderWidth:1.0];
    [iv.layer setBorderColor:[[UIColor whiteColor] CGColor]];

    [iv.layer setShadowColor:[[UIColor blackColor] CGColor]];
    [iv.layer setShadowOffset:CGSizeMake(0, 0)];
    [iv.layer setShadowOpacity:0.75];

}
Was it helpful?

Solution

You should avoid manipulating the cell on each load, instead you should adjust the UI when the cell is initialized/created.

To illustrate, every time you scroll a new cell (or multiple) could be loaded using the cellForRowAtIndexPath: method, currently you are doing a lot of view changes in this method, but there could be cases where this is not needed (for example the new cell is the same type as the one just scrolled off screen). Move this UI modification to where the cell is initialized not where the data is swapped. You could do this with a subclass or simply like this.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // Reuse id
    static NSString *identifier1 = @"identifer-1";
    static NSString *identifier2 = @"identifier-2";
    static NSString *regular = @"regular";

    UITableViewCell *cell;

    if (comment.isReply == NO) {
        cell = [tableView dequeueReusableCellWithIdentifier: identifier1];

        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: identifier1] autorelease];

            // Do the UI modification here
        }
    } else if (comment.isReply == YES) {
        cell = [tableView dequeueReusableCellWithIdentifier: identifier2];

        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: identifier2] autorelease];

            // Do the UI modification here
        }
    } else {
        // Regular cell
        cell = [tableView dequeueReusableCellWithIdentifier: regular];

        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: regular] autorelease];
        }
    }

    // Load the data into the cell

    return cell;
}

Hope you get where I'm going with this, the key is to do heavy stuff as little as possible and let the UITableView caching have a greater effect.

OTHER TIPS

In addition to the other optimization advice here, specifying a shadowPath on your CALayer will improve shadow drawing performance. You could determine a path for the shadow with something like this...

iv.layer.shadowPath = [UIBezierPath bezierPathWithRect:iv.bounds].CGPath;

You may also want to look into the shouldRasterize bit on CALayer. This causes the layer to be pre-rendered as a bitmap. Make sure to also provide a rasterizationScale that matches your device if you go this route.

cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top