我正在尝试在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编程方面很新,我在各地都在搜索解决方案,我仍然不知道: - /有人可以帮我找一些解释这里发生了什么吗?谢谢:))
答案 0 :(得分:5)
在问苹果开发者论坛后,我发现,事实上这是正确分配的内存。这是因为使用-drawRect:绘制的任何视图都将使用(bounds.size.width * bounds.size.height * contentScale * contentScale * 4)字节顺序的内存。
创建避免使用网格的最简单方法是使用为每一行添加一个视图,并使用视图的backgroundColor属性为视图着色。这将几乎不使用任何内存,因为视图(可以是普通的UIViews)不需要调用-drawRect:,因此不会使用额外的内存来存储绘图的结果。