2

私は3つの異なる細胞を持っています。Cell01、Cell02、Cell03。Cell01 は、テーブルビューの上部に 1 回だけ表示する必要があり、残りの 02 と 03 は補間する必要があります (02、03、02、03 (...))。

問題は、TableView をスクロールするときに「ラグ」があることです。ドキュメント フォルダから画像を読み込んでいます。また、あまり処理を必要としないようにサイズを変更していますが、スクロールはまだ遅いです。セルを再利用しています( をチェックしましたif(!cell))。

これが私のコードです:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{    
    int row = indexPath.row;

    if (row == 0) {
        Cell01 *cell = nil;
        cell = [tableView dequeueReusableCellWithIdentifier:@"Cell01ID"];
        if (!cell) {
            cell = (Cell01*)[[[NSBundle mainBundle] loadNibNamed:@"Cell01" owner:self options:nil] objectAtIndex:0];
            cell.someLabel.text = @"First";
            cell.someImage.image = [self imageInDocumentsDirectoryWithName:@"mainimage" andSize:CGSizeMake(200, 200)];
        }

    } else if (row % 2 == 0) {
        Cell02 *cell = nil;
        cell = [tableView dequeueReusableCellWithIdentifier:@"Cell02ID"];
        if (!cell) {
            cell = (Cell02 *)[[[NSBundle mainBundle] loadNibNamed:@"Cell02" owner:self options:nil] objectAtIndex:0];
            cell.randomLabel.text = @"Second";
            cell.someImage.image = [self imageInDocumentsDirectoryWithName:@"secondimage" andSize:CGSizeMake(200, 200)];
        }
    } else {
        Cell03 *cell = nil;
        cell = [tableView dequeueReusableCellWithIdentifier:@"Cell03ID"];
        if (!cell) {
            cell = (Cell03 *)[[[NSBundle mainBundle] loadNibNamed:@"Cell03" owner:self options:nil] objectAtIndex:0];
            cell.anotherLabel.text = @"Third";
            cell.someImage.image = [self imageInDocumentsDirectoryWithName:@"thirdimage" andSize:CGSizeMake(200, 200)];

        }
    }
}


- (UIImage *)imageInDocumentsDirectoryWithName:(NSString *)fileName andSize:(CGSize)size
{    
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString* path = [documentsDirectory stringByAppendingPathComponent:fileName];
    UIImage *image = [UIImage imageWithContentsOfFile:path];
    image = [image resizedImageToFitInSize:size scaleIfSmaller:YES];

    return image;
}

このテーブルビューを改善する (そしてスクロールを速くする) 方法はありますか?

4

4 に答える 4

1

スクロールが遅いのは、ドキュメントディレクトリからセルに画像をロードしているためだと思います。Docディレクトリから画像を取得するには時間がかかり、テーブルビューをスクロールするたびに、新しいセルが作成され、Docディレクトリから画像がロードされますが、これには時間がかかります。セル上の画像の遅延読み込みを使用してみてください。また、メインスレッドではなく、新しいスレッドで画像をロードします..

あなたを助けるAppleのサンプルプロジェクトがあります。テーブルビューの遅延読み込み

これがお役に立てば幸いです。

于 2013-01-12T18:16:26.157 に答える
0

似たようなものの実装を終えたところです。ドキュメント ディレクトリ内のすべての画像が既に正しいサイズ (200 x 200) であることを確認すれば、これは非同期に読み込まなくても問題なく動作します。

画像を大きくする必要がある場合は、元のファイルを保存するときに正しいサイズのサムネイルを生成します。これは、実際には「リアルタイム」で画像のサイズを変更するには処理が多すぎるためです。

ただし、この場合、画像は 3 つしかありません。 サイズ変更後に画像を単純にキャッシュし、(新しい画像を作成する代わりに) 再利用し続けると、それよりもさらに高速になります

于 2013-01-12T19:00:16.853 に答える
0

現在の実装には、潜在的なパフォーマンスの問題が 2 つあります。1 つ目は、nib ファイルをロードするNSBundle代わりに使用する方法です。毎回ファイルシステムから nib ファイルをリロードしますが、nib ファイルを 1 回読み取り、その内容をメモリにキャッシュします。毎回ファイルシステムから nib を再読み込みする必要がないため、オブジェクトのインスタンス化は を使用すると桁違いに速くなります。UINibNSBundleUINibUINib

だから、これをする代わりに...

cell = [[[NSBundle mainBundle] loadNibNamed:@"Cell02" owner:self options:nil] objectAtIndex:0];

...これを行う:

cell = [UINib loadNibNamed:@"Cell02" owner:self] objectAtIndex:0];

2 番目の問題も同様です。現在の実装では、同じ画像をメモリにキャッシュして再利用するのではなく、ファイルシステムから毎回同じ画像を再読み込みしています。NSArrayこれを解決するには、 or型のインスタンス変数を追加しNSDictionary(画像の取得方法に応じて)、画像を読み込む前に、画像が既にコレクションに含まれているかどうかを確認します。そうでない場合は、画像を読み込んでコレクションに保存してから使用してください。それ以外の場合は、再度ロードする代わりに、キャッシュされたイメージを使用しました。

だから、これをする代わりに...

cell.someImage.image = [self imageInDocumentsDirectoryWithName:@"thirdimage" andSize:CGSizeMake(200, 200)];

...次のようにします。

// Note: Consider defining constants for the keys/filenames.

UIImage *image = [self.cachedImages objectForKey:@"thirdimage"];
if (image == nil) {
    image = [self imageInDocumentsDirectoryWithName:@"thirdimage" andSize:CGSizeMake(200, 200)];
    [self.cachedImages setObject:image forKey:@"thirdimage"];
}

cell.someImage.image = image;

この方法で大量の画像をキャッシュする必要がある場合は、キャッシュが大きくなりすぎないようにするために、NSCache代わりにを使用することを検討してください。NSDictionary

于 2013-01-12T20:58:41.023 に答える
0

イメージを非同期でロードすることを検討してください。すべてへの参照をUIImageView変更可能な配列に保持し、たとえば GCD を使用して非同期ブロックで画像の読み込みを開始し、読み込まれたときに画像ビューを更新することができます。

これがどのように見えるかの大まかな例です (これはNSMutableArray *_imageViews、 ivar があり、正しいサイズの要素で初期化され、nil で埋められていることを前提としています)。ここではヒップからコーディングしていますが、アイデアが得られることを願っています. ところで、可変配列に挿入することで、可変配列を nil で埋めることができます[NSNull null]

これを正しく実装すれば、スクロール速度が大幅に向上することをお約束します:)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{    
    int row = indexPath.row;
    if (row == 0) {
        Cell01 *cell = nil;
        cell = [tableView dequeueReusableCellWithIdentifier:@"Cell01ID"];
        if (!cell) {
            cell = (Cell01*)[[[NSBundle mainBundle] loadNibNamed:@"Cell01" owner:self options:nil] objectAtIndex:0];
            cell.someLabel.text = @"First";
            [_imageViews replaceObjectAtIndex:row withObject:cell.someImage];
            dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
            dispatch_async(queue, ^{
                UIImage *image = [self imageInDocumentsDirectoryWithName:@"thirdimage" andSize:CGSizeMake(200, 200)];

                // because UI needs to be updated on the main thread,
                // dispatch yet another block.
                dispatch_async(dispatch_get_main_queue(), ^{
                   UIIMageView *imageView = [_imageViews objectAtIndex:row];
                   ImageView.image = image;
                 });
            });
      }
     // et cetera
}
于 2013-01-12T18:43:06.857 に答える