views:

87

answers:

2

Hi,

I have a view controller whose view consists of a paged scroll view controlled by 2 buttons (previous and next). In this scroll view are several custom views, each the size of one page.

When I load the main view, the scroll view is set up to contain all of these subviews. The performance of my app is currently unacceptable in this area as it takes around 3 seconds for the view to load. I have noticed that if I comment out my drawrect method on my custom view, the performance is improved dramatically. Can someone please have a look over this code and see what I am doing that is so resource hungry? I am really new to core graphics and suspect that I am doing something obviously wrong.

Thanks

- (void)drawRect:(CGRect)rect {
    UILabel *questionNumberLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 40, 200, 50)];
    [questionNumberLabel setBackgroundColor:[UIColor clearColor]];
    [questionNumberLabel setText:[NSString stringWithFormat:@"Question %i", surveyQuestionNumber]];
    [questionNumberLabel setTextAlignment:UITextAlignmentCenter];
    [questionNumberLabel setFont:[UIFont boldSystemFontOfSize:28.0]];
    [questionNumberLabel setTextColor:[UIColor whiteColor]];
    [questionNumberLabel setShadowOffset:CGSizeMake(0, -1.0)];
    [questionNumberLabel setShadowColor:[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5]];
    [self addSubview:questionNumberLabel];
    [questionNumberLabel release];

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGColorRef whiteColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0].CGColor; 
    CGColorRef lightGrayColor = [UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:230.0/255.0 alpha:1.0].CGColor;
    CGColorRef shadowColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:0.5].CGColor;
    CGColorRef lightGreenColor = [[UIColor colorWithRed:158.0/255.0 green:192.0/255.0 blue:72.0/255.0 alpha:1.0] CGColor];
    CGColorRef darkGreenColor = [[UIColor colorWithRed:102.0/255.0 green:142.0/255.0 blue:66.0/255.0 alpha:1.0] CGColor];
    CGColorRef shadowGreenColor = [[UIColor colorWithRed:71.0/255.0 green:100.0/255.0 blue:66.0/255.0 alpha:1.0] CGColor];

    CGFloat outerMargin = 20.0f;
    CGRect outerRect = CGRectInset(self.bounds, outerMargin, outerMargin);
    CGMutablePathRef outerPath = createRoundedRectForRect(outerRect, 15.0);

    CGContextSaveGState(context);
    CGContextSetFillColorWithColor(context, whiteColor);
    CGContextSetShadowWithColor(context, CGSizeMake(0, 5), 5.0, shadowColor);
    CGContextAddPath(context, outerPath);
    CGContextFillPath(context);
    CGContextRestoreGState(context);

    CGContextSaveGState(context);
    CGContextAddPath(context, outerPath);
    CGContextClip(context);
    drawLinearGradient(context, outerRect, whiteColor, lightGrayColor);
    CGContextRestoreGState(context);

    CGContextSaveGState(context);
    CGContextSetLineWidth(context, 2.0);
    CGContextSetStrokeColorWithColor(context, whiteColor);
    CGContextAddPath(context, outerPath);
    CGContextStrokePath(context);
    CGContextRestoreGState(context);

    CGRect ribbonyRect = CGRectMake(10, 40, 220, 50);
    CGContextSaveGState(context);
    CGMutablePathRef ribbonPath = CGPathCreateMutable();
    CGPathMoveToPoint(ribbonPath, NULL, ribbonyRect.origin.x, ribbonyRect.origin.y);
    CGPathAddLineToPoint(ribbonPath, NULL, ribbonyRect.origin.x+ribbonyRect.size.width, ribbonyRect.origin.y);
    CGPathAddLineToPoint(ribbonPath, NULL, ribbonyRect.origin.x+ribbonyRect.size.width-20, ribbonyRect.origin.y+((ribbonyRect.size.height)/2));
    CGPathAddLineToPoint(ribbonPath, NULL, ribbonyRect.origin.x+ribbonyRect.size.width, ribbonyRect.origin.y+ribbonyRect.size.height);
    CGPathAddLineToPoint(ribbonPath, NULL, ribbonyRect.origin.x, ribbonyRect.origin.y+ribbonyRect.size.height);
    CGPathCloseSubpath(ribbonPath);


    CGContextSaveGState(context);
    CGContextSetShadowWithColor(context, CGSizeMake(0, 5), 5.0, shadowColor);
    CGContextAddPath(context, ribbonPath);
    CGContextFillPath(context);
    CGContextRestoreGState(context);

    CGContextAddPath(context, ribbonPath);
    CGContextClip(context);
    drawLinearGradient(context, ribbonyRect, lightGreenColor, darkGreenColor);
    CGContextRestoreGState(context);



    CGContextSaveGState(context);
    CGContextAddPath(context, ribbonPath);
    CGContextSetLineWidth(context, 2.0);
    CGContextSetStrokeColorWithColor(context, lightGreenColor);
    CGContextStrokePath(context);
    CGContextRestoreGState(context);

    CGContextSaveGState(context);
    CGContextAddPath(context, ribbonPath);
    CGContextSetLineWidth(context, 1.5);
    CGContextSetStrokeColorWithColor(context, darkGreenColor);
    CGContextStrokePath(context);
    CGContextRestoreGState(context);


    CGContextMoveToPoint(context, ribbonyRect.origin.x, ribbonyRect.origin.y+ribbonyRect.size.height+1.5);
    CGContextAddLineToPoint(context, 19.0, ribbonyRect.origin.y+ribbonyRect.size.height+1.5);
    CGContextAddLineToPoint(context, 19.0, ribbonyRect.origin.y+ribbonyRect.size.height+12.0);
    CGContextSetFillColorWithColor(context, shadowGreenColor);
    CGContextFillPath(context);

    CFRelease(ribbonPath);
    CFRelease(outerPath);

    questionTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(100.0, 110.0, 568.0, 100.0)];
    [questionTitleLabel setBackgroundColor:[UIColor clearColor]];
    [questionTitleLabel setText:[currentQuestion questionTitle]];
    [questionTitleLabel setFont:[UIFont systemFontOfSize:30.0]];
    [questionTitleLabel setTextAlignment:UITextAlignmentCenter];
    [questionTitleLabel setTextColor:[UIColor grayColor]];
    [questionTitleLabel setShadowColor:[UIColor whiteColor]];
    [questionTitleLabel setShadowOffset:CGSizeMake(0, -1.0)];
    [questionTitleLabel setLineBreakMode:UILineBreakModeWordWrap];
    [questionTitleLabel setNumberOfLines:0];
    [self addSubview:questionTitleLabel];


    questionHintLabel = [[UILabel alloc] initWithFrame:CGRectMake(100.0, 215.0, 568.0, 30.0)];
    [questionHintLabel setBackgroundColor:[UIColor clearColor]];
    [questionHintLabel setText:[currentQuestion questionHint]];
    [questionHintLabel setFont:[UIFont italicSystemFontOfSize:15.0]];
    [questionHintLabel setTextAlignment:UITextAlignmentCenter];
    [questionHintLabel setTextColor:[UIColor grayColor]];
    [questionHintLabel setShadowColor:[UIColor whiteColor]];
    [questionHintLabel setShadowOffset:CGSizeMake(0, -1.0)];
    [self addSubview:questionHintLabel];
}

I have made a gist of my latest code. If someone can have a look at it here, I would really appreciate it

+3  A: 

Two things jump out at me.

1.) Instantiate your UILabels elsewhere - probably in -viewDidLoad. And do necessary setup of UILabels in -viewDidLoad as well. Newing up objects takes time. So, make questionXxxLabel objects ivars.

2.) Along the same lines, create those CGColorRefs somewhere else. They could be static class vars or ivars - but they should be defined once and only once.

For example, you might create a colors.h file that can be included where those colors might be used.

 /*
 * colors.h
 */

//  use _COLORS_ to insure that colors.h is not included multiple times
//  i.e., ANSI standard way of constructing an inclusion guard.

#ifndef _COLORS_
#define _COLORS_

CGColorRef whiteColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0].CGColor; 
CGColorRef lightGrayColor = [UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:230.0/255.0 alpha:1.0].CGColor;
CGColorRef shadowColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:0.5].CGColor;
CGColorRef lightGreenColor = [[UIColor colorWithRed:158.0/255.0 green:192.0/255.0 blue:72.0/255.0 alpha:1.0] CGColor];
CGColorRef darkGreenColor = [[UIColor colorWithRed:102.0/255.0 green:142.0/255.0 blue:66.0/255.0 alpha:1.0] CGColor];
CGColorRef shadowGreenColor = [[UIColor colorWithRed:71.0/255.0 green:100.0/255.0 blue:66.0/255.0 alpha:1.0] CGColor];

#endif // _COLORS_
westsider
As this is in a UIView subclass, there is no viewDidLoad method, would it be ok to move the 'newing up' of the labels (now ivars) into the init method?
Jack
Yes, that would be fine. I should have noticed that...
westsider
+1  A: 

Did you try running your app with Instruments? Maybe it can help you.

Sebastian