0

テーブルビューにサムネイルの行を非同期でロードしようとする次のコードがあります。

for (int i = 0; i < totalThumbnails; i++)
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 
    ^{
        __block GraphicView *graphicView;
        __block Graphic *graphic;

        dispatch_async(dispatch_get_main_queue(), 
        ^{
            graphicView = [[tableViewCell.contentView.subviews objectAtIndex:i] retain];
            graphic = [[self.thumbnailCache objectForKey: [NSNumber numberWithInt:startingThumbnailIndex + i]] retain];

            if (!graphic)
            {
                graphic = [[self graphicWithType:startingThumbnailIndex + i] retain];
                [self.thumbnailCache setObject: graphic forKey:[NSNumber numberWithInt:startingThumbnailIndex + i]];
            }

            [graphicView setGraphic:graphic maximumDimension:self.cellDimension];
        });

        [graphicView setNeedsDisplay];

        dispatch_async(dispatch_get_main_queue(), 
        ^{
            CGRect graphicViewFrame = graphicView.frame;
            graphicViewFrame.origin.x = ((self.cellDimension - graphicViewFrame.size.width) / 2) + (i * self.cellDimension);
            graphicViewFrame.origin.y = (self.cellDimension - graphicViewFrame.size.height) / 2;
            graphicView.frame = graphicViewFrame;
        });

        [graphicView release];
        [graphic release];
    });

}

ただし、コードを実行すると、次の行にアクセスできなくなります。次[graphicView setNeedsDisplay];のように設定すると、コードが正常に動作することに注意してください。

for (int i = 0; i < totalThumbnails; i++)
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 
    ^{
        dispatch_async(dispatch_get_main_queue(), 
        ^{
              //put all the code here
        });
}

それは正常に動作し、UITableView最初に呼び出されたときに非同期にロードされますが、スクロールは依然として非常に途切れ途切れです。

したがって、メイン スレッドではなくグローバル スレッドで描画を実行できるように、コードの最初のビットを機能させるために を取得したいと思います (途切れ途切れのスクロールが修正されると思いますか?)。

iOS4 の描画は非同期で実行できるので、それが問題だとは思いません。おそらく私は__Blockタイプを誤用していますか?

これを機能させる方法を知っている人はいますか?

4

2 に答える 2

2

あなたはGCDの使い方を完全に誤解しています。あなたのコードを見てください:

        __block GraphicView *graphicView;

ここでの変数はnilに初期化されていません。にメッセージを送信することは安全ではありません。

        __block Graphic *graphic;

        dispatch_async(dispatch_get_main_queue(), 
        ^{
            //statements
        });

ここでのディスパッチステートメントはすぐに返されます。システムは、このタスクを別のスレッドでスピンオフするために機能します。上記のステートメントが実行される前、またはおそらく同時に、ここで次の実行行に進みます...

        [graphicView setNeedsDisplay];

この時点で、グラフィックビューは、上記のディスパッチステートメントによって初期化されている場合とされていない場合があります。時間がなかったので、おそらくそうではありません。まだ初期化されていないため、ランダムメモリを指しているため、メッセージを送信しようとするとEXC_BAD_ACCESSが発生します。

セルの内容を非同期で描画する(または画像を事前にレンダリングするなど)場合は、 WWDC2012セッション211「iOSでの同時ユーザーインターフェイスの構築」をよくご覧になることをお勧めします。彼らはあなたがやろうとしているように見えることをほぼ正確に行い、あなたが遭遇する可能性のあるすべての落とし穴を説明します。

于 2012-10-30T09:32:16.080 に答える
0

UIView問題は、作業スレッドで再描画しようとしていることが原因だと思います。これを移動する必要があります:

[graphicView setNeedsDisplay];

メインキューへ。

于 2012-10-30T09:00:58.880 に答える