内存管理多个简单的UIViews

时间:2013-12-08 00:27:31

标签: ios objective-c uiview core-graphics quartz-core

背景:

我正在使用ARC制作基于网格的应用。基本上屏幕中央有一个4x4-8x8网格(占据屏幕的大部分)。这个网格是使用一个UIView构建的,它用一些颜色和用drawRect:绘制的线条着色(我将在下面张贴所有相关代码以供参考)。

对于包含在行的另一个NSMutableArray中的每一行,每个单元格都包含在NSMutableArray中:

  • 数组(行)
    • 阵列(Cols)
      • 单元格内容

在每个单元格中,我有一个actor对象或占位符对象。占位符对象本质上只是一个空白的NSObject,而actor对象有8个基本属性和1个对象属性。

例如,其中一个actor是一个源,它基本上递归地从源中跨越网格绘制一个普通的UIView,直到它击中另一个actor或网格的墙。

enter image description here

蓝色和红色线条显示当前正在运行的不同UIViews。网格这么小,记忆似乎不是常见问题;然而,当完整游戏以8x8网格运行时,除了作为源,动作等的UIImageViews以及不包括的其他UILabel和按钮之外,屏幕上还可以有50多个绘制的UIViews。在网格中。屏幕上可以同时轻松显示超过100个UIViews,即使在具有最佳硬件的最新设备上,也会导致一些非常糟糕的延迟。

我觉得这与我一次向屏幕呈现100多个视图这一事实有关。

问题:

我可以将所有这些动态绘制的线条合并到一个视图中,还是完全有更好的解决方案?

的drawRect:

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGColorRef color = [[self backgroundColor] CGColor];

    int numComponents = CGColorGetNumberOfComponents(color);

    CGFloat red = 0, green = 0, blue = 0;

    if (numComponents == 4)
    {
        const CGFloat *components = CGColorGetComponents(color);
        red = components[0];
        green = components[1];
        blue = components[2];
    }

    CGContextSetRGBFillColor(context, red, green, blue, 0.5);

    float top;
    float cell = [self cellWidth];
    float grid = [self gridWidth];

    //Draw
    for(int i = 0; i < [self size]+1; i++)
    {
        top = i*(cell+lineWidth);

        CGContextFillRect(context, CGRectMake(0, top, grid, lineWidth));
        CGContextFillRect(context, CGRectMake(top, 0, lineWidth, grid));
    }
}

addSources:

- (void)addSources:(NSArray*)sources
{
    for(int i = 0; i < [sources count]; i++)
    {
        NSArray* src = [sources objectAtIndex:i];

        int row = [[src objectAtIndex:1] intValue];
        int column = [[src objectAtIndex:0] intValue];
        int direction = [[src objectAtIndex:2] intValue];
        int color = [UIColor colorKeyForString:[src objectAtIndex:3]];

        float width = [self cellWidth]*scaleActors;
        float x = lineWidth + (([self cellWidth]+lineWidth) * (column-1)) + (([self cellWidth]-width)/2.0);
        float y = lineWidth + (([self cellWidth]+lineWidth) * (row-1)) + (([self cellWidth]-width)/2.0);

        ActorView* actor = [[ActorView alloc] initWithFrame:CGRectMake(x, y, width, width)];
        [actor setType:4];
        [actor setDirection:direction];
        [actor setColorKey:color];
        [actor setIsGlowing:YES];
        [actor setPicture];

        if([self isCreatingLevel])
            [actor setCanRotate:YES];

        [self addSubview:actor];

        [[[self rows] objectAtIndex:(row-1)] replaceObjectAtIndex:(column-1) withObject:actor];
    }
}

编辑:时间分析器结果

到目前为止,我在屏幕上有大约48个绘制的视图(总共约70个视图)。

enter image description here

1 个答案:

答案 0 :(得分:1)

我建议使用WWDC 2012视频iOS App Performance: Responsiveness作为使用Instruments追踪这些问题的良好入门书。该视频中有很多好的技巧和提示。

但我同意这些观点看起来并不古怪(尽管我可能很想在CoreGraphics中渲染这一点)。我没有使用相同的模型,但这是一个纯图形渲染的图形,只有一个UIView子类:

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    // configure the gridlines

    CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]);
    CGContextSetLineWidth(context, 8.0);
    CGContextSetLineCap(context, kCGLineCapSquare);

    // add the horizontal gridlines

    for (NSInteger row = 0; row <= self.rows; row++)
    {
        CGPoint from = [self coordinateForX:0     Y:row];
        CGPoint to   = [self coordinateForX:_cols Y:row];
        CGContextMoveToPoint(context, from.x, from.y);
        CGContextAddLineToPoint(context, to.x, to.y);
    }

    // add the vertical gridlines

    for (NSInteger col = 0; col <= self.cols; col++)
    {
        CGPoint from = [self coordinateForX:col Y:0    ];
        CGPoint to   = [self coordinateForX:col Y:_rows];
        CGContextMoveToPoint(context, from.x, from.y);
        CGContextAddLineToPoint(context, to.x, to.y);
    }

    // stroke the gridlines

    CGContextStrokePath(context);


    // now configure the red/blue line segments

    CGContextSetLineWidth(context, self.bounds.size.width / _cols / 2.0);
    CGContextSetLineCap(context, kCGLineCapRound);

    // iterate through our array of points

    CGPoint lastPoint = [self.points[0] CGPointValue];
    for (NSInteger i = 1; i < [self.points count]; i++)
    {
        // set the color

        if (i % 2)
            CGContextSetStrokeColorWithColor(context, [[UIColor redColor] CGColor]);
        else
            CGContextSetStrokeColorWithColor(context, [[UIColor blueColor] CGColor]);

        CGPoint nextPoint = [self.points[i] CGPointValue];

        // create path

        CGPoint from = [self coordinateForCenterX:lastPoint.x Y:lastPoint.y];
        CGPoint to   = [self coordinateForCenterX:nextPoint.x Y:nextPoint.y];
        CGContextMoveToPoint(context, from.x, from.y);
        CGContextAddLineToPoint(context, to.x, to.y);

        // stroke it

        CGContextStrokePath(context);

        // save the last point

        lastPoint = nextPoint;
    }
}

screen snapshot

现在,也许你正在做其他需要更复杂处理的事情,在这种情况下,WWDC视频(或者,iOS App Performance: Graphics and Animations)应该指向正确的方向。