2

Apple Weatherアプリと同様に、ページング付きのUIScrollViewを使用してアプリを実装したいと思います。

しかし、私はパフォーマンスについて少し心配しています。私が使用している実装例では、すべてのビューが読み込まれ、アプリケーションが起動します。ある時点の後、これが遅いことが判明したら?

Appleのカメラロールはこれをどのように処理しているのだろうか。ユーザーは100枚以上の写真をスクロールできる可能性がある。必要なときにだけビューを作成する方法を見つけようとすべきですか?または、各ビューのレイアウトが同じであるため、水平ビューの読み込みの場合にのみ、UITableViewから再利用可能なセルのデキュー手法を複製する方法があるかもしれません。

4

2 に答える 2

4

はるかに効率的なソリューション(そしてこれはFacebookなどの多くの写真閲覧アプリで使用されており、おそらくネイティブの写真アプリでも使用されています)は、UITableViewと同様に、コンテンツをオンデマンドでロードすることです。AppleのStreetScrollerサンプルプロジェクトはあなたを正しい軌道に乗せるはずです。

于 2012-05-14T03:35:02.363 に答える
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 に答える