かなりの数のタスクをシリアル キューにディスパッチする iOS アプリに取り組んでいます。タスクは、Web サーバーから画像をダウンロードし、ディスクに保存して、後で に表示することUIImageView
です。ただし、[NSURLConnection sendAsynchrousRequest]
iOS がプロセスを強制終了するまで、ますます多くのメモリを消費し続けます。
ダウンローダーの方法は次のようになります。
// dispatch_queue_t is created once by: m_pRequestQueue = dispatch_queue_create( "mynamespace.app", DISPATCH_QUEUE_SERIAL);
- (void) downloadImageInBackgroundWithURL:(NSString*) szUrl {
__block typeof(self) bSelf = self;
__block typeof(m_pUrlRequestQueue) bpUrlRequestQueue = m_pRequestQueue;
dispatch_async( m_pRequestQueue, ^{
NSAutoreleasePool *pAutoreleasePool = [[NSAutoreleasePool alloc] init];
NSURLRequest *pRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:szUrl]
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:URL_REQUEST_TIMEOUT];
[NSURLConnection sendAsynchronousRequest:pRequest queue:bpUrlRequestQueue completionHandler:^(NSURLResponse *pResponse, NSData *pData, NSError *pError) {
NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
if ( pError != nil ) {
} else {
// convert image to png format
UIImage *pImg = [UIImage imageWithData:pData];
NSData *pDataPng = UIImagePNGRepresentation(pImg);
bool bSaved = [[NSFileManager defaultManager] createFileAtPath:szCacheFile contents:pDataPng attributes:nil];
}
__block typeof(pDataPng) bpDataPng = pDataPng;
__block typeof(pError) bpError = pError;
dispatch_sync( dispatch_get_main_queue(), ^ {
NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
UIImage *pImage = [[UIImage alloc] initWithData:bpDataPng];
// display the image
[pImage release];
// NSLog( @"image retain count: %d", [pImage retainCount] ); // 0, bad access
[autoreleasepool drain];
});
}
[pPool drain];
}]; // end sendAsynchronousRequest
[pAutoreleasePool drain];
}); // end dispatch_async
} // end downloadImageInBackgroundWithURL
[NSURLConnection sendAsynchronousRequest]
プロファイラーが関数がすべてのメモリを消費するものであることを示しているので、それは内部にあると確信しています...
ただし、dispatch_*** とブロックのことについてもよくわかりません。以前は常に pthread で C および C++ コードを使用していましたが、スレッドからの移行に関する Apple のドキュメントを読んだ後、GCD を試してみることにしました。 、objective-c はとても面倒で、and をリリースするたびにクラッシュするので、解放する方法がわかりませNSData *pData
んNSURLResponse *pResponse
。
アドバイスをお願いします...客観的なCを学び、理解するために本当に助けが必要です...
追加の編集:
@robhayward のおかげで、pImg と pDataPng を __block 変数として外部に配置し、RHCacheImageView によるデータのダウンロード方法 ( NSData initWithContentOfURL ) を使用しました。
@JorisKluivers のおかげで、UIImageView が jpg と png 形式の両方を認識したので、最初の UIImage を実際に再利用して表示することができます。後で処理するには png 形式が必要であり、後で必要なときにディスクから読み取っています。