モチベーション
UITableViewを使ってニュースアプリのテーブルを作っていました。以下はニュースアプリのGunosyの一部ですが、こんな感じのやつです。
作ってみて実機で動かす段階で、記事をスクロールするとカクカク動いてスクロールが気持ち悪くなってしまいました。
なので、それを解消したいと思いました。
結論としてはライブラリを入れてちょこっと書き換えれば出来ました。
原因
【swift】uitableviewが重いときに対処すべき2つのこと
というのを見て、
- セルの高さ
- セルの画像
をキャッシュする必要があることが分かりました。
セルの高さは指定していたので、原因がセルの画像にあるのだろうと推測出来ました。
画像の最適化
画像のキャッシュ系で使えるライブラリは以下のどれかなのかなーっというのが軽く検索した印象でした。
- AlmofireImage
- SDWebImage
- 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
}
以上で、さくさくの動きになりました!