2012-01-22 11 views
1

バックグラウンドスレッドのURLからUIImageをロードし、水平ページングされたスクロールビューで表示するiOSプロジェクトで作業しています。この動作は、iPhone向けのネイティブフォトライブラリアプリケーションの動作に似ています。私は動作するはずと信じていた方法ですべてのものを設定しているが、主なUIのグラフィックスコンテキストでUIImagesを描く時に、私は時折、コンソールでこのメッセージの印刷を参照してください。バックグラウンドスレッドでUIImageをロードするとImageIOエラーが発生する

ImageIO: <ERROR> CGImageReadSessionGetCachedImageBlockData *** CGImageReadSessionGetCachedImageBlockData: bad readSession [0x685e590] 

このエラーにもかかわらず、それはと思われますアプリは完璧に機能し、画像は期待どおりに描画されます。この「エラー」を無視するか、バックグラウンドスレッドで画像を読み込む方法を変更する必要がありますか?現在、私はUIImage initWithData:メソッドを使用してバックグラウンドスレッドで画像を読み込む:

- (void)backgroundLoadThread:(NSURL *)url { 
    @autoreleasepool { 
     NSData * imageData = [NSData dataWithContentsOfURL:url]; 
     UIImage * theImage = [[UIImage alloc] initWithData:imageData]; 
     if ([[NSThread currentThread] isCancelled]) { 
#if !__has_feature(objc_arc) 
      [theImage release]; 
#endif 
      return; 
     } 
     [self performSelectorOnMainThread:@selector(loadComplete:) 
           withObject:theImage waitUntilDone:NO]; 
    } 
} 

loadComplete:方法は、単に、後でビューのdrawRect:方法で描かれているインスタンス変数として渡された画像を保持します。 drawRect:では、UIImage drawInRect:メソッドを使用していますが、これはコンソールに表示されるエラーメッセージの犯行者です。ただし、画像の基になるCGImageRefをCGContextDrawImageで描画すると、同じエラーが発生します。完全なソースコードは、このプロジェクトのGithubリポジトリのファイルANAsyncImageView.mにあります。

EDIT:ファイルからCGImageを読み込み、フリースレッドを使ってCGImageRefを渡してメインスレッドにコールバックするように変更しました。残念ながら、これは、UIImageのimageWithCGImage:が何らかの形で元のCGImageへの参照を保持しなければならないことを証明して、同じ問題を作り出します。完全なコードのために(GitHubのリポジトリに)上にリンクされたファイル内のコードをチェックアウト:

NSData * imageData = [NSData dataWithContentsOfURL:url]; 
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)imageData); 
CGImageRef loaded = CGImageCreateWithPNGDataProvider(provider, NULL, false, kCGRenderingIntentDefault); 
CGDataProviderRelease(provider); 

id imageObj = (id)loaded;   
[self performSelectorOnMainThread:@selector(loadComplete:) withObject:imageObj waitUntilDone:NO]; 
CGImageRelease(loaded); 
+0

スレッドがキャンセルされているかどうかにかかわらず、そのイメージを公開してはいけませんか? 'performSelectorOnMainThread:withObject:waitUntilDone:'はあなたのためにオブジェクトを保持して解放するので、あなたの下で死ぬことを心配する必要はありません。 –

+0

まず最初にこの回答を見てください:https://stackoverflow.com/a/26562349/1084174 –

答えて

6

UIKitはスレッドセーフなクラスではありません。したがって、UIImageをバックグラウンドから呼び出すべきではありません。

UIImagesを作成するのではなく、イメージファイルをCGImageRefsにレンダリングします。これらのうちの1つをメインスレッドに渡して、そこからUIImageを生成することができます(イメージの圧縮解除を背景に移動することで、まだメリットがあります)。

+0

バックグラウンドスレッドがCGImageRefをロードし、メインスレッドに渡して、それを使ってUIImageを作成するように変更しました。 'imageWithCGImage:'。同じメッセージが引き続きコンソールに表示されます。 –

+0

この場合、この回答は単に問題を解決しません。 –

+0

デバイスやシミュレータで実行していますか?関係なく同じエラーが出ますか? – isaac

関連する問題