在UIScrollView的子视图中绘制网格会分配大量内存 [英] Drawing a grid in UIScrollView's subview allocates huge memory

查看:86
本文介绍了在UIScrollView的子视图中绘制网格会分配大量内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to create a UIView in UIScrollView that contains just a simple grid (lines as rows and columns) drown by UIBezierPath or using the CG functions. The problem is, that when I have larger content size of the UIScrollView (as well as the larger subview), during the drawing of the grid huge amount of memory is allocated (50MB or more).

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

UIViewController which includes just UIScrollView over whole scene - adding subview in 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(网格中一个单元格的宽度/高度):

Inner view that just draw the grid using UIBezierPath/CG functions - depends on properties size(rows/columns count) and cellSize (width/height of one cell in grid):

#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 => contentSize是2000x2000点以及内部视图帧=> 18行被淹没它分配~60MB内存

Example1: self.size is 10, self.cellSize is 200 => contentSize is 2000x2000 points as well as frame of inner view => 18 lines are drown and it allocates ~60MB memory

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

Example2: self.size is 30, self.cellSize is 70 => contentSize is 2100x2100 points as well as frame of inner view => 58 lines are drown and it allocates ~67MB memory

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

These memory numbers I can see when debug the drawing method. No matter how I draw the lines, huge amount of memory is allocated when calling [path stroke] resp. CGContextStrokePath(context). In instruments I can see the biggest memory allocation at line:

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

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

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

I'm quite new in iOS programming and I was searching the solution everywhere and I still have no idea :-/ Can anyone please help me find some explanation what is going on here? Thanks :)

推荐答案

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

After asking on apple developer forum, I find out, that this is properly allocated memory in fact. It's because any view that uses -drawRect: to draw will use memory on the order of (bounds.size.width * bounds.size.height * contentScale * contentScale * 4) bytes.

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

The simplest way to create a grid that avoids that is to use add a view for each line and use the view's backgroundColor property to color the view. This will use hardly any memory because the view's (which can be plain UIViews) don't need to call -drawRect:, and thus won't use extra memory to store the results of your drawing.

这篇关于在UIScrollView的子视图中绘制网格会分配大量内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆