21
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SDWebImageのメモ

Last updated at Posted at 2016-09-19

SDWebImageのメモ

SDWebImageは、Web上の画像をダウンロードして使うのに便利な、定番っぽいライブラリの一つです。

ダウンロードが完了した時にフェードイン

キャッシュにあった場合は何もしないですぐに表示、新たにダウンロードした場合のみ、フェードインで表示するようにします。

  imageView.setShowActivityIndicatorView(true)
  imageView.sd_setImageWithURL(thumbnailURL) {
    image, error, cacheType, imageUrl in
    imageView.setShowActivityIndicatorView(false)
    if error != nil { return }
    if image != nil && cacheType == .None {
      imageView.alpha = 0
      UIView.animateWithDuration(0.5) {
        imageView.alpha = 1
      }
    }
  }

オリジナルサイズの画像をロードする間、サムネールがキャッシュにあれば、それをplaceholderに使う

オリジナル画像と同じアスペクト比のサムネールがあれば、先に粗い写真を表示しておいて、オリジナルのダウンロードが終わると、写真の解像度が上がる、といった事をやりたかったので、調べてみました。

sd_setImageWithURL()は、placeholderにUIImageしか受け取ってくれないので、メモリキャッシュのUIImageを同期で取り出す方法を調べてみました。

Version 5.x (追記)

ちょっとハマったので追記。

    let manager = SDWebImageManager.sharedManager()
    let key = manager.cacheKeyForURL(thumbnailURL)
    let thumbnailImage = (manager.imageCache as? SDImageCache)?.imageFromMemoryCache(forKey: key) ?? emptyImage

    cell.imageView.sd_setImageWithURL(originalPhotoURL, placeholderImage: thumbnailImage)

Version 3.x

import WebImage

class PhotoCollectionViewController: UICollectionViewController {

  // キャッシュがない場合の画像
  let emptyImage = UIImage()

  // ...

  override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("PhotoCollectionViewCell", forIndexPath: indexPath) as! PhotoCollectionViewCell
    cell.imageView.contentMode = .ScaleAspectFit
    let thumbnailURL = photos[indexPath.row].getThumbnailURL()

    // ここから
    let manager = SDWebImageManager.sharedManager()
    let key = manager.cacheKeyForURL(thumbnailURL)
    let thumbnailImage = 
      manager.imageCache.imageFromMemoryCacheForKey(key) ?? emptyImage

    cell.imageView.sd_setImageWithURL(originalPhotoURL, placeholderImage: thumbnailImage)

    return cell
  }
}

サムネールのプリフェッチ

SDWebImageには、画像をあらかじめバックグラウンドでダウンロードしてキャッシュしてくれる機能があります。サムネールをサクサク表示したい時や、上記のように、とりあえず粗い画像でもすぐ出したい、といった時に便利です。

Version 5.x (追記)

ドキュメントによれば、次のprefetchを行っても前のprefetchはキャンセルされなくなり、キャンセルしたい場合は明示的に行うようになったようです。

Version 3.x

実装を見ると、prefetchURLs()を呼ぶと、以前にプリフェッチ中だったURLsは全てキャンセルされるようです。なので、例えば写真のURLの入ったWebAPIのレスポンスを処理した後のタイミングなどで、まとめてprefetchするのがよさげです。

import WebImage

class App {
  let imagePrefetcher = SDWebImagePrefetcher.sharedImagePrefetcher()

  // 沢山の写真のURLが入ったWebAPI
  func getPhotos() {
    var thumbnailURLs = [NSURL]()
    let task = getPhotosTask(params) {
      // response処理の中でthumbnailのURLを集めておく
        thumbnailURLs.append(thumbnailURL)
        // ...
      self.imagePrefetcher.prefetchURLs(thumbnailURLs)
    }
  }
}

追記

上記でも、やはり次のAPI呼び出しで、前のprefechがキャンセルされてしまうので、どうしてもprefetchがキャンセルされるのが嫌なら、外部でキューを管理する、という方法もいいかもしれません。

import WebImage

class App {

    var prefetchURLs = [NSURL]()
    let imagePrefetcher = SDWebImagePrefetcher.sharedImagePrefetcher()

    func loadPhotos() {
        let task = loadPhotosTask(params) {
            // response処理の中でthumbnailのURLを集めておく
            self.prefetchURLs.append(thumbnailURL)
            // ...
            self.startPrefetch()
        }
    }

    func startPrefetch() {
        self.imagePrefetcher.prefetchURLs(prefetchURLs, progress: {
                finished, total in
                assert(NSThread.isMainThread())
                print("\(finished)/\(total)")
            }, completed: {
                finished, skipped in
                assert(NSThread.isMainThread())
                print("Prefetch finished: \(finished) skipped: \(skipped)")
                self.prefetchURLs.removeAll()
            })
    }
}

コールバックもMain Threadで呼ばれるようなので、すり抜けも起こらなさそうです。

21
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?