Help us understand the problem. What is going on with this article?

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
    }

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away