Pav*_*kal 1 memory drawing uiscrollview ios 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
Run Code Online (Sandbox Code Playgroud)
仅使用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
Run Code Online (Sandbox Code Playgroud)
例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 0x10200000 VM:CoreAnimation 00:04.092.149•67,29 MB QuartzCore CA :: Render :: Shmem :: new_shmem(unsigned long)
我在iOS编程方面很新,我在各处搜索解决方案,我仍然不知道: - /有谁能帮我找一些解释这里发生了什么?谢谢 :)
在询问苹果开发者论坛后,我发现,事实上这是正确分配的内存.这是因为使用-drawRect:绘制的任何视图都将使用(bounds.size.width*bounds.size.height*contentScale*contentScale*4)字节顺序的内存.
创建避免使用网格的最简单方法是使用为每一行添加一个视图,并使用视图的backgroundColor属性为视图着色.这将几乎不使用任何内存,因为视图(可以是普通的UIViews)不需要调用-drawRect:,因此不会使用额外的内存来存储绘图的结果.