Search code examples
iphonecocoa-touchuitableviewcore-animationcore-graphics

Optimizing drawing on UITableViewCell


I am drawing content to a UITableViewCell and it is working well, but I'm trying to understand if there is a better way of doing this.

Each cell has the following components:

  • Thumbnail on the left side - could come from server so it is loaded async
  • Title String - variable length so each cell could be different height
  • Timestamp String
  • Gradient background - the gradient goes from the top of the cell to the bottom and is semi-transparent so that background colors shine through with a gloss

It currently works well. The drawing occurs as follows:

  • UITableViewController inits/reuses a cell, sets needed data, and calls

    [cell setNeedsDisplay]

  • The cell has a CALayer for the thumbnail - thumbnailLayer

  • In the cell's drawRect it draws the gradient background and the two strings

  • The cell's drawRect it then calls setIcon - which gets the thumbnail and sets the image as the contents of the thumbnailLayer. If the image is not found locally, it sets a loading image as the contents of the thumbnailLayer and asynchronously gets the thumbnail. Once the thumbnail is received, it is reset by calling setIcon again & resets the thumbnailLayer.contents

This all currently works, but using Instruments I see that the thumbnail is compositing with the gradient. I have tried the following to fix this:

  • setting the cell's backgroundView to a view whose drawRect would draw the gradient so that the cell's drawRect could draw the thumbnail and using setNeedsDisplayInRect would allow me to only redraw the thumbnail after it loaded --- but this resulted in the backgroundView's drawing (gradient) covering the cell's drawing (text).

  • I would just draw the thumbnail in the cell's drawRect, but when setNeedsDisplay is called, drawRect will just overlap another image and the loading image may show through. I would clear the rect, but then I would have to redraw the gradient.

  • I would try to draw the gradient in a CAGradientLayer and store a reference to it, so I can quickly redraw it, but I figured I'd have to redraw the gradient if the cell's height changes.

Any ideas? I'm sure I'm missing something so any help would be great.

Bump - anyone have any ideas for this?


Solution

  • I started using setNeedsDisplayInRect. I still draw everything in drawRect but when I do, I check the rect that needs to be drawn and only update that rect. I also draw using CGLayers and keep them as ivars. When I need to redraw a section that hasn't changed, I use the stored CGLayer. The thumbnail is no longer a CALayer. For drawing selects I will have to use the selectedBackgroundView and reuse my CGLayers.