我想使用带分页的UIScrollView实现一个应用程序,类似于苹果天气应用程序。
但我对性能有点担心。我一直在使用的示例实现加载所有视图然后应用程序启动。经过一定时间点,一旦证明这一点很慢?
我想知道Apple的相机是如何处理的,用户可能会有100多张可以滚动的照片。我是否应该尝试找出一种仅在需要时构建视图的方法?或者也许有一种方法可以从UITableView复制出列可重用单元格技术,仅用于水平视图加载,因为每个视图都具有相同的布局。
答案 0 :(得分:4)
到目前为止,最有效的解决方案(在许多照片浏览应用程序中使用,例如Facebook,也可能是原生照片应用程序)将按需加载内容,就像UITableView一样。 Apple的StreetScroller示例项目应该让您走上正轨。
答案 1 :(得分:4)
一个非常有效的解决方案是确保尽可能重用任何视图。如果您要简单地显示图像,可以使用UIScrollView的子类,并在layoutSubviews中布局这些可重用的视图。在这里,您可以检测哪些视图可见且不可见,并根据需要创建子视图。
示例出列函数可能如下所示:
- (UIImageView *)dequeueReusableTileWithFrame:(CGRect) frame andImage:(UIImage *) image
{
UIImageView *tile = [reusableTiles anyObject];
if (tile) {
[reusableTiles removeObject:tile];
tile.frame = frame;
}
else {
tile = [[UIImageView alloc] initWithFrame:frame];
}
tile.image = image;
return tile;
}
其中reusableTiles只是NSMutableSet类型的iVar。然后,您可以使用它来加载任何当前屏幕外的图像视图,并快速轻松地将它们带回到视图中。
您的layoutSubviews可能类似于:
- (void)layoutSubviews {
[super layoutSubviews];
CGRect visibleBounds = [self bounds];
CGPoint contentArea = [self contentOffset];
//recycle all tiles that are not visible
for (GSVLineTileView *tile in [self subviews]) {
if (! CGRectIntersectsRect([tile frame], visibleBounds)) {
[reusableTiles addObject:tile];
[tile removeFromSuperview];
}
}
int col = firstVisibleColumn = floorf(CGRectGetMinX(visibleBounds)/tileSize.width);
lastVisibleColumn = floorf(CGRectGetMaxX(visibleBounds)/tileSize.width) ;
int row = firstVisibleRow = floorf(CGRectGetMinY(visibleBounds)/tileSize.height);
lastVisibleRow = floorf(CGRectGetMaxY(visibleBounds)/tileSize.height);
while(row <= lastVisibleRow)
{
col = firstVisibleColumn;
while (col <= lastVisibleColumn)
{
if(row < firstDisplayedRow || row > lastDisplayedRow || col < firstDisplayedColumn || col >lastDisplayedColumn)
{
UImageView* tile = [self dequeueReusableTileWithFrame:CGRectMake(tileSize.width*col, tileSize.height*row, tileSize.width, tileSize.height) andImage:YourImage];
[self addSubview:tile];
}
++col;
}
++row;
}
firstDisplayedColumn = firstVisibleColumn;
lastDisplayedColumn = lastVisibleColumn;
firstDisplayedRow = firstVisibleRow;
lastDisplayedRow = lastVisibleRow;
}
当我使用滚动视图的特别大的区域时,我使用了与此类似的东西来平铺线条区域并且它似乎工作得很好。对于我为图像视图而不是我的自定义tileView类更新此错误时可能创建的任何拼写错误。