需求加载一个 UIScrollView

Posted

技术标签:

【中文标题】需求加载一个 UIScrollView【英文标题】:Demand loading a UIScrollView 【发布时间】:2012-05-14 02:50:27 【问题描述】:

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

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

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

【问题讨论】:

【参考方案1】:

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

【讨论】:

我在页面控制演示developer.apple.com/library/ios/#samplecode/PageControl/…987654322@上建模了我的实现【参考方案2】:

一个非常有效的解决方案是确保尽可能重用任何视图。如果您只想显示图像,则可以使用 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 类更新此内容时可能创建的任何拼写错误,我深表歉意。

【讨论】:

以上是关于需求加载一个 UIScrollView的主要内容,如果未能解决你的问题,请参考以下文章

m3m4加载器的优化版1.0,能满足基本需求了

Bitmap

C++-加载EXCEL数据

Vue Element表格实现滚动加载

Vue Element表格实现滚动加载

winform异步加载数据到界面