UITableView
Swift
SDWebImage
Swift3.0

Swift3 表示画像を最適化してUITableViewのスクロールをさくさくさせる

More than 1 year has passed since last update.

モチベーション

UITableViewを使ってニュースアプリのテーブルを作っていました。以下はニュースアプリのGunosyの一部ですが、こんな感じのやつです。

gunosy.jpg

作ってみて実機で動かす段階で、記事をスクロールするとカクカク動いてスクロールが気持ち悪くなってしまいました。
なので、それを解消したいと思いました。

結論としてはライブラリを入れてちょこっと書き換えれば出来ました。

原因

【swift】uitableviewが重いときに対処すべき2つのこと

というのを見て、

  1. セルの高さ
  2. セルの画像

をキャッシュする必要があることが分かりました。

セルの高さは指定していたので、原因がセルの画像にあるのだろうと推測出来ました。

画像の最適化

画像のキャッシュ系で使えるライブラリは以下のどれかなのかなーっというのが軽く検索した印象でした。

  1. AlmofireImage
  2. SDWebImage
  3. KingFisher

以下の記事が参考になりました。
B2B2Cなヘルスケアサービスの作り方

Q. なんでSDWebImageを使ってないのか?

A.
Pure Swiftで書かれたライブラリで統一したかったから
画像fetchするベンチマーク結果はほぼ変わらなかった
Kingfisherも候補だったがAlamofireを導入済だったのでこちらに

定番なのはどうやらSDWebImageみたいなのですがswiftでは書かれていないのがネックで、AlmofireImageだとswiftで書かれてるみたいです。Alamofireを既に使っていたのでKingfisherを使うくらいならAlmofireなのかなと思ってKingfisherは選択肢から外しました。
そして、Pure Swiftにこだわってないので定番のSDWebImageでいいかなと思って結局SDWebImageを選択しました。

実装

pod install

まず、SDWebImageをインストールします。
以下のようにコードをPodfileに入れてpod install

pod 'SDWebImage'

ブリッジヘッダファイル

そして、SDWebImageはObjective-Cのコードなのでブリッジヘッダファイル(Swiftで使えるようにしてくれるやつ)に以下を挿入します。

#import "SDWebImage/UIImageView+WebCache.h"

ブリッジヘッダファイルがない場合(デフォルトではない)は作らないといけません。
僕はiOS初心者がSwiftでグノシーみたいなタブ型RSSリーダーを作ってみたを参考にブリッジヘッダファイルを作成しました。

コード

以下のように画像を呼び出している箇所を変更するだけ(sd_setImageを使うだけ)で終わりです。

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
      let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath as IndexPath) as! CustomTopViewCell
      cell.title.text = self.entries[indexPath.row]["title"].string
      cell.site.text = self.entries[indexPath.row]["supported_site"]["name"].string

      // 以下3行部分
      let url = NSURL(string: self.entries[indexPath.row]["main_image_url"].string!)
      let imageData :Data = try! Data(contentsOf: url! as URL)
      cell.thumbnail.image = UIImage(data:imageData as Data)!

      return cell
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
      let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath as IndexPath) as! CustomTopViewCell
      cell.title.text = self.entries[indexPath.row]["title"].string
      cell.site.text = self.entries[indexPath.row]["supported_site"]["name"].string

      // 以下2行に変更
      let url = NSURL(string: self.entries[indexPath.row]["main_image_url"].string!)
      cell.thumbnail.sd_setImage(with: url as URL?)

      return cell
    }

以上で、さくさくの動きになりました!