加载滚动视图时性能不佳

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 的滚动性能不佳 - 分析指向可访问性调用

重新加载滚动视图的内容

加载数据后如何防止滚动视图滚动到网络视图?

在中心视图上滑动时,使用 iCarousel 加载 webView 不会滚动

滚动回收器视图中的滞后

表视图单元格在重新加载表视图和滚动时重复内容