使用CGContextFillRect突然出现内存峰值

时间:2013-10-11 20:18:21

标签: ios objective-c cocoa-touch core-graphics cgcontext

我在下面的代码中看到“CGContextFillRect”语句执行时内存使用量急剧增加(从iPad上的39 MB到186 MB)。这里有什么问题。

我的申请最终崩溃了。

PS:令人惊讶的是,内存峰值出现在第3代和第4代iPad上,而不是第2代iPad上。

    - (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setBackgroundColor:[UIColor clearColor]];
    }
    return self;
}


- (id)initWithFrame:(CGRect)iFrame andHollowCircles:(NSArray *)iCircles {

    self = [super initWithFrame:iFrame];
    if (self) {
        [self setBackgroundColor:[UIColor clearColor]];
        self.circleViews = iCircles;
    }
    return self;
}


- (void)drawHollowPoint:(CGPoint)iHollowPoint withRadius:(NSNumber *)iRadius {
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(currentContext, self.circleRadius.floatValue);
    [[UIColor whiteColor] setFill];
    CGContextAddArc(currentContext, iHollowPoint.x, iHollowPoint.y, iRadius.floatValue, 0, M_PI * 2, YES);
    CGContextFillPath(currentContext);
}


- (void)drawRect:(CGRect)rect {
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGContextSaveGState(currentContext);
    CGRect aRect = [self.superview bounds];
    [[UIColor whiteColor]setFill];
    CGContextFillRect(currentContext, aRect);

    CGContextSaveGState(currentContext);
    [[UIColor blackColor]setFill];
    CGContextFillRect(currentContext, aRect);
    CGContextRestoreGState(currentContext);

    for (MyCircleView *circleView in self.circleViews) {
        [self drawHollowPoint:circleView.center withRadius:circleView.circleRadius];
    }

    CGContextTranslateCTM(currentContext, 0, self.bounds.size.height);
    CGContextScaleCTM(currentContext, 1.0, -1.0);
    CGContextSaveGState(currentContext);
}

1 个答案:

答案 0 :(得分:1)

这段代码没有多大意义;我假设你已经删除了它的一部分?您创建一个空白的alpha蒙版,然后将其丢弃。

如果上面的代码真的是你正在做的,你真的不需要绘制任何东西。您可以创建一个12MB的内存区域并用重复的1 0 0 0(ARGB中的不透明黑色)填充它,然后创建一个图像。但我认为你实际上做的不仅仅是那个。

可能您将此视图配置为contentScaleFactor设置为与scale中的UIScreen匹配,此视图非常大。第3代和第4代iPad都有Retina显示屏,因此比例为2,绘制视图所需的内存是4倍。

那就是说,你应该只想要大约12MB来保持全屏图像(2048 * 1536 * 4)。事实上,你看到10x表明会发生更多事情,但我怀疑它仍然与绘制太多副本有关。

如果可能,您可以将比例降低到1,使视网膜和非视网膜的行为相同。


编辑:

您编辑的代码与原始代码非常不同。没有尝试在此代码中制作图像。我尽我所能地测试了它,并且我没有看到任何令人惊讶的记忆峰值。但有几个奇怪之处:<​​/ p>

  • 您未正确平衡CGContextSaveGStateCGContextRestoreGState。这实际上可能会导致内存问题。
  • 你为什么要用白色绘制矩形,然后全部用黑色绘制?
  • 你的直肠是[self.superview bounds]。那是在错误的坐标空间。你应该几乎肯定是[self bounds]
  • 为什么在从drawRect返回之前翻转上下文然后保存上下文?这根本没有意义。

我认为你的drawRect:看起来像这样:

- (void)drawRect:(CGRect)rect {
  [[UIColor blackColor] setFill];
  UIRectFill(rect); // You're only responsible for drawing the area given in `rect`

  for (CircleView *circleView in self.circleViews) {
    [self drawHollowPoint:circleView.center withRadius:circleView.circleRadius];
  }
}