【问题标题】:Sudden memory spike with CGContextFillRect使用 CGContextFillRect 突然出现内存峰值
【发布时间】:2013-10-20 00:43:38
【问题描述】:

在下面的代码中执行“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);
}

【问题讨论】:

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


    【解决方案1】:

    这段代码不太合理;我假设你已经删除了它的一部分?您创建一个空白 Alpha 蒙版,然后将其丢弃。

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

    您可能已将此视图配置为将contentScaleFactor 设置为匹配来自UIScreenscale,并且此视图非常大。第 3 代和第 4 代 iPad 具有 Retina 显示屏,因此比例为 2,绘制视图所需的内存是原来的 4 倍。

    也就是说,您应该只期望大约 12MB 来容纳全屏图像 (2048*1536*4)。您看到 10 倍的事实表明正在发生更多事情,但我怀疑这仍然可能与绘制过多副本有关。

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


    编辑:

    您编辑的代码与原始代码有很大不同。没有尝试在此代码中制作图像。我已经尽我所能对其进行了测试,我没有看到任何令人惊讶的内存峰值。但是有几个奇怪的地方:

    • 您没有正确平衡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];
      }
    }
    

    【讨论】:

    • 是的,罗伯。你是对的,我做的比我之前粘贴的要多。我已经输入了我的确切代码。我想做的是在我的视野中画出空心圆圈。我用 BezierPaths 尝试过,但是当圆圈相交时,它的行为与偶数/奇数填充规则很奇怪。你能帮我解决视网膜设备的这个内存问题吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-13
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2014-12-01
    相关资源
    最近更新 更多