加载滚动视图时性能不佳
Posted
技术标签:
【中文标题】加载滚动视图时性能不佳【英文标题】:Poor performance loading a scroll view 【发布时间】:2010-10-26 16:22:25 【问题描述】:我有一个视图控制器,它的视图由一个由 2 个按钮(上一个和下一个)控制的分页滚动视图组成。在这个滚动视图中有几个自定义视图,每个视图大小为一页。
当我加载主视图时,滚动视图设置为包含所有这些子视图。我的应用程序的性能目前在这方面是不可接受的,因为加载视图大约需要 3 秒。我注意到,如果我在自定义视图上注释掉我的 drawrect 方法,性能会显着提高。有人可以看看这段代码,看看我在做什么,这太耗资源了吗?我对核心图形真的很陌生,并且怀疑我做错了什么。
谢谢
- (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];
我对我的最新代码做了一个要点。如果有人可以看一下here,我将不胜感激
【问题讨论】:
不要在drawRect:
中添加或修改子视图。每次调用drawRect:
时,您都会添加另一组子视图,而不会删除已经存在的子视图。
能否详细说明提取方法?我想你是说这段代码不应该在drawrect中,但我不知道它应该去哪里?
【参考方案1】:
我突然想到了两件事。
1.) 在其他地方实例化您的 UILabel - 可能在 -viewDidLoad 中。并在 -viewDidLoad 中进行必要的 UILabel 设置。更新对象需要时间。因此,将 questionXxxLabel 对象设为 ivars。
2.) 沿着同样的思路,在其他地方创建这些 CGColorRef。它们可以是静态类 vars 或 ivars - 但它们应该被定义一次且仅一次。
例如,您可以创建一个 colors.h 文件,该文件可以包含在可能使用这些颜色的位置。
/*
* 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_
【讨论】:
由于这是在 UIView 子类中,没有 viewDidLoad 方法,是否可以将标签的“更新”(现在是 ivars)移动到 init 方法中? 嗨 Westsider,我应该在哪里创建 CGColorRefs?我对添加它们的最佳位置感到困惑。我用我最新的代码为这个问题添加了一个要点。谢谢 与 UIView 子类中的 -(void)viewDidLoad 类似,您可以使用 -(void)layoutSubviews 方法。在那里你可以分配你需要的任何对象。【参考方案2】:您是否尝试过使用 Instruments 运行您的应用程序?也许它可以帮助你。
【讨论】:
以上是关于加载滚动视图时性能不佳的主要内容,如果未能解决你的问题,请参考以下文章
UICollectionView 的滚动性能不佳 - 分析指向可访问性调用