避免UIView创建非常大的绘图画布

时间:2011-08-26 12:57:22

标签: iphone ios uiview uiscrollview

我从UIView派生了一个类,但却意识到由于内存的存在,它的大小存在实际限制。我在UIScrollView中有这个UIView。

有没有办法让我把一些东西放在一个滚动视图里面,这个视图不是一个UIView派生类,但是我仍然可以绘制它,哪个可以非常大?

我不介意必须响应expose-rectangle事件,就像使用传统窗口系统时那样。

感谢。

2 个答案:

答案 0 :(得分:5)

UIScrollView内的内容必须为UIViews,由于内存原因,这些内容因大小而受限制。出于性能原因,UIView维护一个位图后备存储,因此它必须按照其大小分配内存。

处理此问题的常用方法是生成多个UIViews并在用户滚动时将其交换出来。另一个版本是使用CATiledLayer。但是,这些都没有给你“巨型帆布”绘图模型。你应该根据需要分解并绘制它们。不过,这是通常的做法。

如果你真的想要一个巨型画布,我的推荐是CGPDFContext。现有丰富的支持,特别是使用UIWebView(请记住,您可以打开data: URI以避免从磁盘读取文件)。您可以通过应用仿射变换然后CGContextDrawPDFPage直接绘制它们的一部分。 CGBitmapContext是另一种方法,但它可能需要更多的内存来进行少量绘图。

答案 1 :(得分:2)

所以UIView内有UIScrollView,但您希望UIView的边界非常大(即,它与UIScrollView的大小匹配s contentSize)。但是你不想在每次需要显示时绘制整个UIView,也不能一次将其全部内容放在内存中。

UIView使用CAScrollLayer支持,如下所示:

// MyCustomUIView.m

+ (Class) layerClass
{
    return [CAScrollLayer class];
}

当用户滚动包含UIScrollView的{​​{1}}时,添加一种更新滚动位置的方法:

UIView

确保在绘制// MyCustomUIView.m - (void) setScrollOffset:(CGPoint)scrollOffset { CAScrollLayer *scrollLayer = (CAScrollLayer*)self.layer; [scrollLayer scrollToPoint:scrollOffset]; } 时,只绘制提供给您的UIView中包含的部分:

CGRect

现在,在您的- (void)drawRect:(CGRect)rect { // Only draw stuff that lies inside 'rect' // CGRectIntersection might be handy here! } 中,当父UIScrollViewDelegate更新时,您需要通知CAScrollLayer支持的视图:

UIScrollView

您还可以使用// SomeUIScrollViewDelegate.m - (void) scrollViewDidScroll:(UIScrollView *)scrollView { // Offset myCustomView within the scrollview so that it is always visible myCustomView.frame = CGRectMake(scrollView.contentOffset.x, scrollView.contentOffset.y, scrollView.bounds.size.width, scrollView.bounds.size.height); // "Scroll" myCustomView so that the correct portion is rendered [myCustomView setScrollOffset:self.contentOffset]; // Tell it to update its display [myCustomView setNeedsDisplay]; } ,这更容易,因为您不必跟踪滚动位置 - 而是根据需要调用每个图块的CATiledLayer方法。但是,这会导致您的视图缓慢淡入。如果您打算缓存部分视图并且不介意缓慢更新,则可能需要这样做。