drawrect 在非常大的 uiview 和内存不足

Posted

技术标签:

【中文标题】drawrect 在非常大的 uiview 和内存不足【英文标题】:drawrect in very large uiview and memory is not sufficient 【发布时间】:2013-09-29 18:03:55 【问题描述】:

我正在编写一个用户可以在 uiview 上绘制的应用程序。如果该 uiview 是正常大小(比如说 1024 x 720),它会完美运行。但是,如果我将其添加到 uiscrollview 并且该尺寸为 1024 x 3000,它会变得非常慢。另外,如果高度为 10000,应用程序会当场崩溃。我想知道怎么做。

- (void) drawRect: (CGRect) rect

    NSLog(@"drawrect here 1");

if (self.arrayStrokes)

    int arraynum = 0;
    // each iteration draw a stroke
    // line segments within a single stroke (path) has the same color and line width
    for (NSDictionary *dictStroke in self.arrayStrokes)
    
        NSArray *arrayPointsInstroke = [dictStroke objectForKey:@"points"];
        UIColor *color = [dictStroke objectForKey:@"color"];
        float size = [[dictStroke objectForKey:@"size"] floatValue];
        [color set];        // equivalent to both setFill and setStroke

        //          // won't draw a line which is too short
        //          if (arrayPointsInstroke.count < 3)  
        //              arraynum++; 
        //              continue;       // if continue is executed, the program jumps to the next dictStroke
        //          

        // draw the stroke, line by line, with rounded joints
        UIBezierPath* pathLines = [UIBezierPath bezierPath];
        CGPoint pointStart = CGPointFromString([arrayPointsInstroke objectAtIndex:0]);
        [pathLines moveToPoint:pointStart];
        for (int i = 0; i < (arrayPointsInstroke.count - 1); i++)
        
            CGPoint pointNext = CGPointFromString([arrayPointsInstroke objectAtIndex:i+1]);
            [pathLines addLineToPoint:pointNext];
        
        pathLines.lineWidth = size;
        pathLines.lineJoinStyle = kCGLineJoinRound;
        pathLines.lineCapStyle = kCGLineCapRound;
        [pathLines stroke];

        arraynum++;
    


【问题讨论】:

【参考方案1】:

在提供的代码示例中没有任何明显的东西会导致非常大的视图出现问题。我做了一个快速测试,并绘制了一个 1024 x 10,000 的视图,没有任何事故。我通过 Instruments 运行了这个版本,结果非常令人满意:

您应该通过 Instruments 运行您的应用,并且 (a) 确保没有泄漏; (b) 查看分配并确保其水平。如果它在你身上增长,你应该确定是什么导致了增长(通过 option-在分配窗口中拖动或执行 heapshots)。大量问题可能导致分配增长(CGRelease 某些核心基础对象失败,上下文开始/结束不匹配等),所以我犹豫猜测您的问题可能是什么。在您提供的代码示例中,我没有看到任何明显的内容。我只建议通过静态分析器(“产品”菜单上的“分析”)运行您的代码,看看它是否能识别任何东西。

现在,问题在于使用renderInContextUIGraphicsGetImageFromCurrentImageContext() 将其保存为UIImage。您还没有说您正在这样做,但是尝试创建/保存图像会消耗这些大小的惊人内存量。

如果您不熟悉使用 Instruments 跟踪内存问题,我建议您观看 WWDC 2012 视频 ios App Performance: Memory。这是一个很好的主题入门。

【讨论】:

是的。这是我的结果。 i40.tinypic.com/sbkidc.png 。如果可能的话,你能检查一下这个代码吗? mediafire.com/download/i8jxi71it8p87tu/smoothline.zip 。我在 uiwebview 滚动视图上使用该 uiview。我不确定是什么导致应用变慢和崩溃。 这是我在uiwebview滚动视图中绘制的完整源代码。我收到内存警告。 mediafire.com/?jg7d6a5q2dsai4s @KhantThuLinn 我们应该将此移至聊天:chat.***.com/rooms/38356/…【参考方案2】:

如果手机不允许您创建比这更大的 CGrect,这是有原因的,如果手机内存不足,您几乎无能为力,请尝试使用不同的解决方案解决您的问题,但内存不足手机的数量是有限的,你不能滥用。

【讨论】:

【参考方案3】:

这是因为UIView会在你实现-drawRect:函数时分配内存。

这就是答案 Drawing a grid in UIScrollView's subview allocates huge memory

【讨论】:

以上是关于drawrect 在非常大的 uiview 和内存不足的主要内容,如果未能解决你的问题,请参考以下文章

加速 -drawRect: UIView 子类的方法

简单的 UIView drawRect 没有被调用

避免 UIView 创建非常大的绘图画布

跨多个 UIView 子类的单个 drawRect 实现

空drawRect实现导致内存警告

如果初始帧为 CGRectZero,则不会调用自定义 UIView 的 drawRect