2

我想使用带有分页的 UIScrollView 实现一个应用程序,类似于苹果天气应用程序。

但我有点担心性能。我一直在使用的示例实现加载所有视图,然后应用程序启动。在某一点之后,一旦证明这很慢?

我想知道苹果的相机胶卷是如何处理这个问题的,用户可能有 100 多张可以滚动浏览的照片。我是否应该尝试找出一种仅在需要时才构建视图的方法?或者也许有一种方法可以从 UITableView 复制出列可重用单元技术,仅用于水平视图加载,因为每个视图将具有相同的布局。

4

2 回答 2

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 类更新此内容时可能创建的任何拼写错误,我深表歉意。

于 2012-05-14T04:19:02.890 回答
4

到目前为止,最有效的解决方案(这在许多照片浏览应用程序中使用,例如 Facebook,也可能是本地照片应用程序)将是按需加载内容,就像 UITableView 所做的那样。Apple 的StreetScroller示例项目应该让您走上正轨。

于 2012-05-14T03:35:02.363 回答