Is anyone else out there using the UACellBackgroundView code to do cell gradients. It works like a champ and I want to continue using it, but it is leaking like a sieve.
I think instruments says that CGPathCreateMutable() is creating a mutable copy but not releasing. This is a little deeper than my memory management skills.
Here is the code I am using: Header:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef enum {
UACellBackgroundViewPositionSingle = 0,
UACellBackgroundViewPositionTop,
UACellBackgroundViewPositionBottom,
UACellBackgroundViewPositionMiddle
} UACellBackgroundViewPosition;
@interface UACellBackgroundView : UIView {
UACellBackgroundViewPosition position;
}
@property(nonatomic) UACellBackgroundViewPosition position;
@end
Class file:
//
// UACellBackgroundView.m
// Ambiance
//
// Created by Matt Coneybeare on 1/31/10.
// Copyright 2010 Urban Apps LLC. All rights reserved.
//
#define TABLE_CELL_BACKGROUND { 1, 1, 1, 1, 0.866, 0.866, 0.866, 1} // #FFFFFF and #DDDDDD
#define kDefaultMargin 10
#import "UACellBackgroundView.h"
static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth,float ovalHeight);
@implementation UACellBackgroundView
@synthesize position;
- (BOOL) isOpaque {
return NO;
}
-(void)drawRect:(CGRect)aRect {
// Drawing code
int lineWidth = 1;
CGRect rect = [self bounds];
rect.size.width -= lineWidth;
rect.size.height -= lineWidth;
rect.origin.x += lineWidth / 2.0;
rect.origin.y += lineWidth / 2.0;
CGFloat minx = CGRectGetMinX(rect), midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect);
CGFloat miny = CGRectGetMinY(rect), midy = CGRectGetMidY(rect), maxy = CGRectGetMaxY(rect);
maxy += 1;
CGFloat locations[2] = { 0.0, 1.0 };
CGContextRef c = UIGraphicsGetCurrentContext();
CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef myGradient = nil;
CGFloat components[8] = TABLE_CELL_BACKGROUND;
//CGContextSetStrokeColorWithColor(c, [[UAColor tableCellBorderColor] CGColor]);
CGContextSetStrokeColorWithColor(c, [[UIColor grayColor] CGColor]);
CGContextSetLineWidth(c, lineWidth);
CGContextSetAllowsAntialiasing(c, YES);
CGContextSetShouldAntialias(c, YES);
if (position == UACellBackgroundViewPositionTop) {
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, minx, maxy);
CGPathAddArcToPoint(path, NULL, minx, miny, midx, miny, kDefaultMargin);
CGPathAddArcToPoint(path, NULL, maxx, miny, maxx, maxy, kDefaultMargin);
CGPathAddLineToPoint(path, NULL, maxx, maxy);
CGPathAddLineToPoint(path, NULL, minx, maxy);
CGPathCloseSubpath(path);
// Fill and stroke the path
CGContextSaveGState(c);
CGContextAddPath(c, path);
CGContextClip(c);
myGradient = CGGradientCreateWithColorComponents(myColorspace, components, locations, 2);
CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);
CGContextAddPath(c, path);
CGContextStrokePath(c);
CGContextRestoreGState(c);
} else if (position == UACellBackgroundViewPositionBottom) {
maxy -= 1;
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, minx, miny);
CGPathAddArcToPoint(path, NULL, minx, maxy, midx, maxy, kDefaultMargin);
CGPathAddArcToPoint(path, NULL, maxx, maxy, maxx, miny, kDefaultMargin);
CGPathAddLineToPoint(path, NULL, maxx, miny);
CGPathAddLineToPoint(path, NULL, minx, miny);
CGPathCloseSubpath(path);
// Fill and stroke the path
CGContextSaveGState(c);
CGContextAddPath(c, path);
CGContextClip(c);
myGradient = CGGradientCreateWithColorComponents(myColorspace, components, locations, 2);
CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);
CGContextAddPath(c, path);
CGContextStrokePath(c);
CGContextRestoreGState(c);
} else if (position == UACellBackgroundViewPositionMiddle) {
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, minx, miny);
CGPathAddLineToPoint(path, NULL, maxx, miny);
CGPathAddLineToPoint(path, NULL, maxx, maxy);
CGPathAddLineToPoint(path, NULL, minx, maxy);
CGPathAddLineToPoint(path, NULL, minx, miny);
CGPathCloseSubpath(path);
// Fill and stroke the path
CGContextSaveGState(c);
CGContextAddPath(c, path);
CGContextClip(c);
myGradient = CGGradientCreateWithColorComponents(myColorspace, components, locations, 2);
CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);
CGContextAddPath(c, path);
CGContextStrokePath(c);
CGContextRestoreGState(c);
} else if (position == UACellBackgroundViewPositionSingle) {
maxy -= 1;
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, minx, midy);
CGPathAddArcToPoint(path, NULL, minx, miny, midx, miny, kDefaultMargin);
CGPathAddArcToPoint(path, NULL, maxx, miny, maxx, midy, kDefaultMargin);
CGPathAddArcToPoint(path, NULL, maxx, maxy, midx, maxy, kDefaultMargin);
CGPathAddArcToPoint(path, NULL, minx, maxy, minx, midy, kDefaultMargin);
CGPathCloseSubpath(path);
// Fill and stroke the path
CGContextSaveGState(c);
CGContextAddPath(c, path);
CGContextClip(c);
myGradient = CGGradientCreateWithColorComponents(myColorspace, components, locations, 2);
CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);
CGContextAddPath(c, path);
CGContextStrokePath(c);
CGContextRestoreGState(c);
}
CGColorSpaceRelease(myColorspace);
CGGradientRelease(myGradient);
return;
}
- (void)dealloc {
[super dealloc];
}
- (void)setPosition:(UACellBackgroundViewPosition)newPosition {
if (position != newPosition) {
position = newPosition;
[self setNeedsDisplay];
}
}
@end
static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth,float ovalHeight) {
float fw, fh;
if (ovalWidth == 0 || ovalHeight == 0) {// 1
CGContextAddRect(context, rect);
return;
}
CGContextSaveGState(context);// 2
CGContextTranslateCTM (context, CGRectGetMinX(rect),// 3
CGRectGetMinY(rect));
CGContextScaleCTM (context, ovalWidth, ovalHeight);// 4
fw = CGRectGetWidth (rect) / ovalWidth;// 5
fh = CGRectGetHeight (rect) / ovalHeight;// 6
CGContextMoveToPoint(context, fw, fh/2); // 7
CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);// 8
CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);// 9
CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);// 10
CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); // 11
CGContextClosePath(context);// 12
CGContextRestoreGState(context);// 13
}