SDWebImageでダウンロードした画像のファイルパスを取得して画像を扱う

March 22, 2015

手順

まずはやり方を記述します。

SDWebImageManagerでダウンロードする

[[SDWebImageManager sharedManager] downloadImageWithURL:url
                                                options:SDWebImageRetryFailed
                                               progress:nil
                                              completed:^(UIImage *image, NSError *_error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
                                              	//完了処理. 以下を参照
                                              }];

URLからキャッシュキーを取得して、diskImageExistsWithKey:completion:で確認する.

NSString *cacheKey = [[SDWebImageManager sharedManager] cacheKeyForURL:imageURL];
NSString *cachePath = [[SDImageCache sharedImageCache] defaultCachePathForKey:cacheKey];
[[SDImageCache sharedImageCache] diskImageExistsWithKey:cacheKey completion:^(BOOL isInCache) {
    if (isInCache) {
		// ここでようやく使えるようになる
    }
}];

ポイント

diskImageExistsWithKey:でなくてdiskImageExistsWithKey:completion:であることがポイントで、completedのタイミングではファイルの書き込みが完了しているとは限りません。ダウンロード完了後、ディスクへの書き込み処理はSDImageCacheioQueueにdispatchされているだけです。

// ダウンロード後の書き込み処理
[self.imageCache storeImage:downloadedImage recalculateFromImage:NO imageData:data forKey:key toDisk:cacheOnDisk];
// storeImage:recalculateFromImage:imageData:forKey:toDisk:のおおまかな流れ
if (toDisk) {
    dispatch_async(self.ioQueue, ^{
	    ...
		[_fileManager createFileAtPath:[self defaultCachePathForKey:key] contents:data attributes:nil];
	})
}

diskImageExistsWithKey:completion:は存在確認処理をioQueueにdispatchします。

- (BOOL)diskImageExistsWithKey:(NSString *)key {
    BOOL exists = NO;

    // this is an exception to access the filemanager on another queue than ioQueue, but we are using the shared instance
    // from apple docs on NSFileManager: The methods of the shared NSFileManager object can be called from multiple threads safely.
    exists = [[NSFileManager defaultManager] fileExistsAtPath:[self defaultCachePathForKey:key]];

    return exists;
}

- (void)diskImageExistsWithKey:(NSString *)key completion:(SDWebImageCheckCacheCompletionBlock)completionBlock {
    dispatch_async(_ioQueue, ^{
        BOOL exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key]];
        if (completionBlock) {
            dispatch_async(dispatch_get_main_queue(), ^{
                completionBlock(exists);
            });
        }
    });
}

ioQueueはシリアルキューなので存在確認処理は必ず書き込み完了後になります。

_ioQueue = dispatch_queue_create("com.hackemist.SDWebImageCache", DISPATCH_QUEUE_SERIAL);
このエントリーをはてなブックマークに追加