4

画像を表示するUITableViewがあります。すべてのセルには画像があり、セルが読み込まれるたびに、次のようにバックグラウンドでセレクター(cellForRowAtIndexPathから)を呼び出します。

[self performSelectorInBackground:@selector(lazyLoad:) withObject:aArrayOfData];

唯一の問題は、クラッシュすることがあることです(他の場所で読み取ろうとしているときにバックグラウンドでデータを変更しているため)。エラーは次のとおりです。

*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <CALayerArray: 0xce1a920> was mutated while being enumerated.'

バックグラウンドでデータを更新する場合、メインセレクターに移動して変更する必要がありますか?または、@ selector()を別の方法で呼び出す必要がありますか?

ありがとう!

4

3 に答える 3

3

メインスレッドで操作を終了でき、遅延や問題がなければ完了です。

ただし、すでにそれを実行していて、問題が発生していると仮定しましょう。答えは次のとおりです。レイジーロードでアレイ変更しないでください。メインスレッドに切り替えて、アレイを変更します。ここでブラッドの答えを参照してください:

https://stackoverflow.com/a/8186206/8047

ブロックを使用してそれを行う方法として、オブジェクトをメインキューに送信できます(最初に遅延ロードの呼び出しにもGCDを使用する必要がありますが、必須ではありません)。

于 2012-04-21T04:27:47.830 に答える
1

@synchronizedブロックを使用して、スレッドが相互に移動しないようにすることができます。もし、するなら

@synchronized(array)
{
  id item = [array objectAtIndex:row];
}

メインスレッドで

@synchronized(array)
{
  [array addObject:item];
}

バックグラウンドでは、それらが同時に発生しないことが保証されています。(うまくいけば、それからコードに外挿することができます。そこでの配列で何をしているのかわかりません。)

ただし、セルのデータをロードしたことをメインスレッドに通知する必要があるようです(たとえば、performSelectorOnMainThread:withObject:waitUntilDone:を介して)。データも渡してみませんか?

于 2012-04-21T05:57:46.687 に答える
0

「遅延読み込み」という用語を考えると、サーバーからイメージをプルダウンしていることを意味していると思います。(画像がローカルの場合、マルチスレッドは実際には必要ありません)。

サーバーから画像をダウンロードする場合は、これらの行に沿って何かを使用することをお勧めします(ASIHTTPRequestを使用)

   static NSCache *cellCache; //Create a Static cache

    if (!cellCache)//If the cache is not initialized initialize it
    {
        cellCache = [[NSCache alloc] init];
    }
    NSString *key = imageURL;
    //Look in the cache for image matching this url
    NSData *imageData = [cellCache objectForKey:key];

    if (!imageData)
    {
        //Set a default image while it's loading
        cell.icon.image = [UIImage imageNamed:@"defaultImage.png"];'

        //Create an async request to the server to get the image
        __unsafe_unretained ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:imageURL]];


        //This code will run when the request finishes
        [request setCompletionBlock:^{
            //Put downloaded image into the cache
            [cellCache setObject:[request responseData] forKey:key];
            //Display image
            cell.icon.image = [UIImage imageWithData:[request responseData]];
        }];
        [request startAsynchronous];
    }
    else 
    {
        //Image was found in the cache no need to redownload
        cell.icon.image = [UIImage imageWithData:imageData];
    }
于 2012-04-21T05:57:01.967 に答える