2017年6月15日木曜日

Swift3 で画像を良い感じにキャッシュしてくれる Kingfisher を使ってみた

概要

UITableView の UITableViewCell 内に ImageView がありテーブルをスクロールするたびに画像をダウンロードするアプリがありました
Android と同様でセルが表示されるたびに画像をダウンロードしてしまう仕様でかなりいけていませんでした
そんなとき Kingfisher という素晴らしいライブラリに出会いこれがやりたいことを完璧にやってくれたので使い方を紹介します

環境

  • macOS 10.12.5
  • Xcode 8.3.3 (8E3004b)
  • Kingfisher 3.3.3

インストール

Podfile に以下を追記して install するだけです

pod 'Kingfisher'

使いたい .swift ファイルの先頭で import しましょう

import Kingfisher

画像を読み込む

今まで以下のようなコードで UITableViewCell 内の ImageView に画像をダウンロードして設定していました

let imageURL: NSURL? = NSURL(string: img["src"]!)
let req = NSURLRequest(url: imageURL! as URL)
NSURLConnection.sendAsynchronousRequest(req as URLRequest, queue: OperationQueue.main) { (res, data, err) in
    let image = UIImage(data: data!)
    imageView.image = image
}

これが cellForRowAt メソッドで実装されているためセルが表示されるたびに sendAsynchronousRequest が使われるため無駄に通信を行っていました

これを Kingfisher を使って以下のように書き換えます

imageView.kf.indicatorType = .activity
imageView.kf.setImage(with: URL(string: img["src"]!),
                      // キャッシュがある場合はキャッシュを使用する
                      completionHandler: {
                        (image, error, cacheType, imageURL) in
                        imageView.image = image
})

まだ画像がダウンロードできていない場合には URL から画像をダウンロードします
そして、ダウンロード中はインジケータを表示します
画像がダウンロードできているセルにスクロールした場合には completionHandler 側がコールされすでにキャッシュされている image を imageView に設定するだけでキャッシュが利用できます

動作確認

アプリをビルドして確認してみましょう
改修前はスクロールするたびに画像をダウンロードするため、回線状況の悪い場合だとセルに正しい画像が表示されなかたり、画像の表示が追いつかなかったりします

Kingfisher を使った改修後はセルをスクロールしまくってもダウンロード中にインジケータが表示されるし、ダウンロードが完了した画像はキャッシュから表示してくれるため、画像の表示が遅れたりすることが一切ありません

比較のスクリーンショットがないのが残念ですがかなり快適な感じになると思います

またアプリを kill して再度立ち上げてもキャッシュが残っている状態だったのですでにダウンロード済みの画像に関してはすぐに表示されました

最後に

Swift で Kingfisher を使ってみました
かなり良い感じのライブラリでビックリしました
Swift には他にも同じようなライブラリがあるようで Moa や Vincent, MapleBacon などあるようです
今回 Kingfisher を使ったのは単純に一番人気そうだったので使いましたが他のやつも代用可能だと思います

画像ダウンロード系はもう全部 Kingfisher を使っていこうと思います

参考サイト

0 件のコメント:

コメントを投稿