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

查看:15
本文介绍了在 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 - 在 vi​​ewDidLoad 中添加子视图:

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] 时都会分配大量内存.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 属性为视图着色.这几乎不会占用任何内存,因为视图(可以是普通的 UIView)不需要调用 -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天全站免登陆