In my app I have a UIImageView in a UITableViewCell. The images need to be displayed as circular images with rectangular source images. I have been setting the corner radius on the imageView's layer property, but this forces an offscreen render which is slowing performance on scrolling.
Here's what I currently have in the awakeFromNib method on the cells:
- (void)awakeFromNib
{
[super awakeFromNib];
self.imageBorderView.backgroundColor = [UIColor colorWithWhite:0.75f alpha:1.f];
self.imageBorderView.layer.cornerRadius = self.imageBorderView.frame.size.width / 2;
}
Really basic stuff. Ok, so I just watched the 2011 WWDC Session 121 video, Understanding UIKit Rendering. That covered this issue as it relates to a UILabel by moving the corner radius rendering to drawRect using UIBezierPaths. I subclassed UIImageView and moved my cornerRadius drawing to drawRect only to find that drawRect is not called on a UIImageView. Here's the relevant reasoning from the docs:
The UIImageView class is optimized to draw its images to the display. UIImageView does not call the drawRect: method of its subclasses. If your subclass needs to include custom drawing code, you should subclass the UIView class instead.
So I changed the superclass to UIView and I am manually drawing a circle using UIBezierPath and the UIImage in drawRect. Here is my drawRect method:
- (void)drawRect:(CGRect)rect
{
UIBezierPath *circularPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.bounds.size.height / 2.0];
[[UIColor redColor] set];
[circularPath fill];
if (self.image)
{
[self.image drawInRect:self.bounds];
}
}
It does exactly what I would expect, it draws the red circle (just a sanity check to make sure the path is correct), then it draws the rectangular image over the circle if one has been set.
What I can't figure out is how to crop the UIImage to the circular UIBezierPath without drawing offscreen. This means setting an object as the mask wont work.
Is there a way to mask an image to a path without rendering offscreen?