【swift4】 imageをcache化する


Swift4でimageをcache化する情報がなかなか見つからなかったので、記載していきたいと思います。
もし間違いなどがあれば、ご指摘いただけると嬉しいです!

まずiOSではNSCacheクラスを用いて、キャッシュ化を行います。

NSCacheについて

イメージなどをURLから読み込むような処理をしていると、毎回読み込みに時間がかかります。そこでイメージをキャシュ化し、iOSのメモリに保存します。それにより、再度読み込む必要がなくなり、処理を高速化します。
ただiOSのメモリが足りなくなってくると、自動的にこのキャッシュはなくなるようにできています。


  • dictionary型と同じで、keyとvalueのセットです。 保存したいデータがvalueになり、保存したデータを取り出すためにkeyを設定しなければなりません。

ex)

static let imageCache = NSCache<AnyObject, AnyObject>()

今回はimageをキャッシュ化するので、UIImageViewのextensionとして定義していきます。

UIImageViewExtension

UIImageViewExtension.swift
import UIKit

extension UIImageView {

    //NSCacheのインスタンスを生成しておく。ここに、どんどんキャッシュ化されたものが保存されていく。
    static let imageCache = NSCache<AnyObject, AnyObject>()

    //読み込むURLのstringを引数にする。
    func cacheImage(imageUrlString: String) {

        //引数のimageUrlStringをURLに型変換する。
        let url = URL(string: imageUrlString)

        //引数で渡されたimageUrlStringがすでにキャッシュとして保存されている場合は、キャッシュからそのimageを取り出し、self.imageに代入し、returnで抜ける。
        if let imageFromCache = UIImageView.imageCache.object(forKey: imageUrlString as AnyObject) as? UIImage {
            self.image = imageFromCache
            return
        }

        //上記のifに引っかからないということは、キャッシュとして保存されていないということなので、以下でキャッシュ化をしていく。
        //URLSessionクラスのdataTaskメソッドで、urlを元にして、バックグランドでサーバーと通信を行う。
        //{ 以降はcompletionHandler(クロージャー)で、通信処理が終わってから実行される。
        //dataはサーバーからの返り値。urlResponseは。HTTPヘッダーやHTTPステータスコードなどの情報。リクエストが失敗したときに、errorに値が入力される。失敗しない限り、nilとなる。
        URLSession.shared.dataTask(with: url!) { (data, urlResponse, error) in

            //errorがnilじゃないということは、リクエストに失敗しているということ。returnで抜け出す。
            if error != nil {
                print(error)
                return
            }

            //リクエストが成功して、サーバーからのresponseがある状態。
            //しかし、UIKitのオブジェクトは必ずメインスレッドで実行しなければならないので、DispatchQueue.mainでメインキューに処理を追加する。非同期で登録するので、asyncで実装。
            DispatchQueue.main.async {

                //サーバーからのレスポンスのdataを元にして、UIImageを取得し、imageToCacheに代入。
                let imageToCache = UIImage(data:data!)

                //self.imageにimageToCacheを代入。
                self.image = imageToCache

                //keyをimageUrlStringとして、imageToCacheをキャッシュとして保存する。
                UIImageView.imageCache.setObject(imageToCache!, forKey: imageUrlString as AnyObject)
            }
        }.resume()
    }
}

実際にこのメソッドを呼んでいるコード

example.swift
import UIKit

class ExampleViewController: UIViewController {

    let imgString = "https://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

    override func viewDidLoad() {
        super.viewDidLoad()

        profileImage.cacheImage(imageUrlString: imgString)

    let profileImage: UIImageView = {
        let image = UIImageView()
        let myColor = UIColor(red: 246/255, green: 177/255, blue: 67/255, alpha: 1)
        image.contentMode = .scaleAspectFill
        image.layer.borderColor = myColor.cgColor
        image.backgroundColor = UIColor.white
        return image
    }()

}