在UIScrollView的子视图中绘制网格会分配大量内存

时间:2014-01-30 01:32:35

标签: ios memory uiscrollview drawing uibezierpath

我正在尝试在UIScrollView中创建一个UIView,它只包含一个由UIBezierPath或CG函数淹没的简单网格(行和行)。问题是,当我有更大的UIScrollView内容大小(以及更大的子视图)时,在绘制网格期间会分配大量内存(50MB或更多)。

UIViewController,它在整个场景中只包含UIScrollView - 在viewDidLoad中添加子视图:

@interface TTTTestViewController()

@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;

@end

@implementation TTTTestViewController

-(void)viewDidLoad
{
    [super viewDidLoad];

    // create the subview
    TTTTestView *testView = [[TTTTestView alloc] init];
    [self.scrollView addSubview:testView];

    //set its properties
    testView.cellSize = 50;
    testView.size = 40;

    // set the content size and frame of testView by the properties
    self.scrollView.contentSize = CGSizeMake(testView.cellSize * testView.size, testView.cellSize * testView.size);
    testView.frame = CGRectMake(0, 0,  self.scrollView.contentSize.width, self.scrollView.contentSize.height);

    // let it draw the grid
    [testView setNeedsDisplay];
}

@end

使用UIBezierPath / CG函数绘制网格的内部视图 - 取决于属性大小(行/列计数)和cellSize(网格中一个单元格的宽度/高度):

#define GRID_STROKE_WIDTH 2.0

@implementation TTTTestView

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

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];
    [self drawGrid];
}

-(void)drawGrid
{
    UIBezierPath *path = [[UIBezierPath alloc] init];

    for (int i = 1; i < self.size; i++) {
            //draw row line
        [path moveToPoint:CGPointMake(0, self.cellSize * i)];
        [path addLineToPoint:CGPointMake(self.bounds.size.width, self.cellSize * i)];
            // draw column line
        [path moveToPoint:CGPointMake(self.cellSize * i, 0)];
        [path addLineToPoint:CGPointMake(self.cellSize * i , self.bounds.size.height)];
    }
    [path setLineWidth:GRID_STROKE_WIDTH];
    [[UIColor blackColor] setStroke];
    [path stroke];
    /*
     CGContextRef context = UIGraphicsGetCurrentContext();

     CGContextSetLineWidth(context, GRID_STROKE_WIDTH);
     CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);

     for (int i = 1; i < self.size; i++) {
     //draw row line
     CGContextMoveToPoint(context, 0, self.cellSize * i );
     CGContextAddLineToPoint(context, self.bounds.size.width, self.cellSize * i);
     // draw column line
     CGContextMoveToPoint(context, self.cellSize * i , 0);
     CGContextAddLineToPoint(context, self.cellSize * i , self.bounds.size.height);
     }

     CGContextStrokePath(context);
     */
}

@end

示例1:self.size是10,self.cellSize是200 =&gt; contentSize是2000x2000点以及内部视图帧=&gt; 18条线被淹没,它分配~60MB内存

示例2:self.size是30,self.cellSize是70 =&gt; contentSize是2100x2100点以及内部视图的帧=&gt; 58条线被淹没,它分配~67MB内存

调试绘图方法时可以看到的这些内存编号。无论我如何绘制线条,在调用[path stroke] resp时都会分配大量内存。 CGContextStrokePath(上下文)。在乐器中我可以看到最大的内存分配:

12658 0x10200000 VM:CoreAnimation 00:04.092.149•67,29 MB QuartzCore CA :: Render :: Shmem :: new_shmem(unsigned long)

我在iOS编程方面很新,我在各地都在搜索解决方案,我仍然不知道: - /有人可以帮我找一些解释这里发生了什么吗?谢谢:))

1 个答案:

答案 0 :(得分:5)

在问苹果开发者论坛后,我发现,事实上这是正确分配的内存。这是因为使用-drawRect:绘制的任何视图都将使用(bounds.size.width * bounds.size.height * contentScale * contentScale * 4)字节顺序的内存。

创建避免使用网格的最简单方法是使用为每一行添加一个视图,并使用视图的backgroundColor属性为视图着色。这将几乎不使用任何内存,因为视图(可以是普通的UIViews)不需要调用-drawRect:,因此不会使用额外的内存来存储绘图的结果。