質問

私は、バックグラウンドで画像をダウンロードするNSOperationQueueを使用していますこんにちは。私は、画像をダウンロードするためのカスタムNSOperationを作成しました。私はテーブルのセルに画像を置きます。 [:10 operationQueue setMaxConcurrentOperationCount]と私はプログラムがEXC_BAD_ACCESSでクラッシュし、いくつかのセルをスクロールダウンし、私がしなければ問題があります。たびに、テーブル内の同じ場所でクラッシュします。 3個の細胞は、同じ会社のためであり、それは、画像を3回をダウンロードする必要がありますので、基本的に同じロゴを持つ他の後の1があります。他のすべての時間は、それが正常に動作します。


- (void) main
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSURL *url = [[NSURL alloc] initWithString:self.imageURL];
    debugLog(@"downloading image: %@", self.imageURL);
    //NSError *error = nil;
    NSData *data = [[NSData alloc] initWithContentsOfURL:url];
    [url release];

    UIImage *image = [[UIImage alloc] initWithData:data];
    [data release];
    if (image)
    {
        if (image.size.width != ICONWIDTH && image.size.height != ICONHEIGHT)
        {
            UIImage *resizedImage;
            CGSize itemSize = CGSizeMake(ICONWIDTH, ICONHEIGHT);

                        //!!! UIGraphicsBeginImageContext NOT THREAD SAFE
            UIGraphicsBeginImageContext(itemSize);
            CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
            [image drawInRect:imageRect];
            resizedImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();

            self.theImage = resizedImage;
        }
        else
        {
            self.theImage = image;
        }
        [image release];
    }
    [delegate didFinishDownloadingImage: self];
    [pool release];
}

これは私が画像をダウンロード処理する方法です。私はコメントアウトした場合 [delegate didFinishDownloadingImage: self]; 上記の関数では、それがクラッシュしませんが、もちろんそれは無用です。


-(void) didFinishDownloadingImage:(ImageDownloadOperation *) imageDownloader
{
    [self performSelectorOnMainThread: @selector(handleDidFinishDownloadingImage:) withObject: imageDownloader waitUntilDone: FALSE];
}

-(void) handleDidFinishDownloadingImage:(ImageDownloadOperation *)imageDownloadOperation
{
    NSArray *visiblePaths = [self.myTableView indexPathsForVisibleRows];
    CompanyImgDownloaderState *stateObject = (CompanyImgDownloaderState *)[imageDownloadOperation stateObject];

    if ([visiblePaths containsObject: stateObject.indexPath])
    {
        //debugLog(@"didFinishDownloadingImage %@ %@", imageDownloader.theImage);

        UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath: stateObject.indexPath];
        UIImageView *imageView = (UIImageView *)[cell viewWithTag: 1];
        if (imageDownloadOperation.theImage)
        {
            imageView.image = imageDownloadOperation.theImage;
            stateObject.company.icon = imageDownloadOperation.theImage;
        }
        else
        {
            imageView.image = [(TestWebServiceAppDelegate *)[[UIApplication sharedApplication] delegate] getCylexIcon];
            stateObject.company.icon = [(TestWebServiceAppDelegate *)[[UIApplication sharedApplication] delegate] getCylexIcon];
        }

    }
}


役に立ちましたか?

解決

このメーリングリストの記事によると、UIGraphicsBeginImageContextはスレッドセーフではありません。ポストヒントCGBitmapContextCreateと関連する関数は、それを行うための安全な方法であることを。

http://osdir.com/ml/cocoa-dev /2009-10/msg00035.htmlする

他のヒント

私はあなたが存在しないテーブルビューにアクセスセルにしようとしているので、あなたがしているがクラッシュと思います。

は関係なく、論理的な表があるどのくらいの、視覚的なテーブルビューは、現在画面上に論理テーブルのセクションを表示するのに十分な細胞を保持しています。デフォルトの行のサイズで、表に示し、したがってのみ9~10セルオブジェクトに含まれています。たとえば、100行の長さである論理テーブルを持っている場合は、あなたのビューは、テーブルのみ9つのセルオブジェクトを持つ11-20行を示しています。あなたが行89-98を示した場合、それが唯一ののの9セルオブジェクトの のまったく同じを持っています。あなたが表示された行に関係なく、あなたは同じ9セルが何度も何度もオブジェクトと参照してください。唯一のことは、変更がデータであることを、彼らが表示されます。

あなたが画面の外論理行のセルにアクセスしようとすると、

、あなたは何のバックを取得することはありません。あなたのケースでは、あなたは、11日の論理的な行にアクセスしようとするが、そこには11番目のセルがなく、存在しませんでした。

私はあなたのセルの内容を設定することにより、テーブルビュー自体にデータを格納しようとしているので、あなたには、いくつかの概念の混乱があると思います。 tableviewsがすぐに表示されているもの以外の任意のデータを格納しないので、これは動作しません。あなたがスクロールするとテーブルビューのニーズはより多くの行を表示する場合は、既存のセルを再利用し、そのデータソースデリゲートは、既存のセルが表示されるようにデータを変更します。

代わりに細胞内で画像を保存するのには、データモデルを作成し、そこに画像を保存する必要があります。そして、テーブルビューのスクロールは、そのデータソースデリゲートにtableview:cellForRowAtIndexPath:を送信するとき。データソースデリゲートはその後、論理行のデータのためのデータモデルを尋ねる再利用し、細胞を移入し、テーブルビューに戻します。

[OK]を、それはのCodeWarrior のおかげで解決しているようです。これが変更されたことを一部です。

@synchronized(delegate)
{
    UIImage *resizedImage;
    UIGraphicsBeginImageContext(itemSize);
    CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
    [image drawInRect:imageRect];
    resizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    self.theImage = resizedImage; 
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top