Ios 在UIScrollView';s子视图分配巨大的内存

Ios 在UIScrollView';s子视图分配巨大的内存,ios,memory,uiscrollview,drawing,uibezierpath,Ios,Memory,Uiscrollview,Drawing,Uibezierpath,我正试图在UIScrollView中创建一个UIView,它只包含一个简单的网格(行和列的线条),被UIBezierPath或使用CG函数淹没。问题是,当我有更大的UIScrollView(以及更大的子视图)内容大小时,在绘制网格时会分配大量内存(50MB或更多) UIViewController,仅包括整个场景上的UIScrollView-在viewDidLoad中添加子视图: @interface TTTTestViewController() @property (weak, nonat

我正试图在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函数绘制网格的内部视图-取决于属性大小(行/列计数)和单元大小(网格中一个单元的宽度/高度):

#定义网格_笔划_宽度2.0
@实现TTTTestView
-(id)initWithFrame:(CGRect)帧
{
self=[super initWithFrame:frame];
如果(自我){
self.backgroundColor=[UIColor clearColor];
}
回归自我;
}
-(void)drawRect:(CGRect)rect
{
[超级drawRect:rect];
[自绘制网格];
}
-(空)绘图网格
{
UIBezierPath*路径=[[UIBezierPath alloc]init];
for(int i=1;i
示例1:self.size为10,self.cellSize为200=>contentSize为2000x2000点,以及内部视图框架=>18行被淹没,并分配约60MB内存

示例2:self.size为30,self.cellSize为70=>contentSize为2100x2100点,以及内部视图框架=>58行被淹没,并分配约67MB内存

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

12658 0x10200000VM:CoreAnimation 00:04.092.149•67,29 MB QuartzCore CA::Render::Shmem::new_Shmem(无符号长)


我对iOS编程非常陌生,我到处都在搜索解决方案,但我仍然不知道:-/有人能帮我找到一些解释吗?谢谢:)

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


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

在apple developer论坛上询问后,我发现这实际上是正确分配的内存。这是因为任何使用-drawRect:进行绘制的视图都将使用(bounds.size.width*bounds.size.height*contentScale*contentScale*4)字节数量级的内存


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

但是在绘图完成后,
CA::Render::Shmem::new_Shmem(unsigned long)
分配的内存不会减少。它将始终是持久性的吗?但是绘制完成后,由
CA::Render::Shmem::new_Shmem(unsigned long)
分配的内存不会减少。会永远是坚持吗?
#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