【Swift5】Cloud Storageから画像をダウンロードしてTableViewに表示する方法

この記事ではCloud Storageにアップロードした画像をダウンロードしてTableView内のimageViewに表示する方法について解説していきます.

Cloud Storageで画像を扱う際に難しいのが素直に実装してしまうと非同期処理になってしまい,TableViewなどでは画像が表示されないことがあるということだと思います.

私もこれについては結構悩まされまして,この度同期処理を実装することなくそのままTableViewでも画像を表示できるようになりましたのでその方法を共有したいと思います.

Podfileの設定

まずは今回使用するライブラリをインストールします.以下の内容をpodfileに追記してください.

pod 'Firebase/Core'
pod 'Firebase/Storage'
pod 'AlamofireImage', '~> 4.1'

そしてpod installを実行すれば準備は完了です.

TableViewの設定

tableViewの設定としてcell内にImageViewが設置されておりそのimageViewに画像を表示することを考えます.この時,画像のダウンロードのためには便利なのでAlamofireImageを使用しちゃいましょう.そのため,cloud storageからはダウンロード用のURLを作成することで画像データをimageViewに表示することにします..
ちなみに以下のコードのstorageImageURL(imagePath)がダウンロードするURLを取得する部分であるが詳しくは後で解説します.

import AlamofireImage

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: K.armListReusableCell, for: indexPath) as! MyTableViewCell

        let imagePath: String = "your imagePath"
        storageImageURL(imagePath) { (urlString) in
                    let url = URL(string: urlString)!
                    cell.imageView.af.setImage(withURL: url)
        }
        
        return cell
    }

Cloud Storageから画像をダウンロード

さて,肝心のCloud Storageからの画像ダウンロードですが,私の場合はダウンロード用のURLを取得してAlamofireImageでその画像をダウンロードするという手法を選択しました.
というわけで公式の通り実装してみたのですがURLのダウンロードに時間がかかってしまい画像が表示されないという問題が発生しました.

その後,このダウンロードの部分を同期処理にしようとしてDispatchQueueのsemaphoreとかも使ってみたのですがうまくいきませんでした.

最終的に画像のダウンロードを扱う部分にcompletionを実装しますとうまくいきましたので以下がコードになります.

import FirebaseStorage

let storage = Storage.storage()

func storageImageURL(_ imagePath: String, completion: @escaping (String) -> Void){
        let storageRef = storage.reference(forURL: "yourStorageURL")
        var returnURL = imagePath
        let imageRef = storageRef.child(imagePath)
        imageRef.downloadURL { url, error in
          if let error = error {
            print("\(error)")
          } else {
            returnURL = url?.absoluteString as! String
            completion(returnURL)
          }
        }
    }

コードの解説

というわけでコードをまとめると以下のような感じです.

import AlamofireImage
import FirebaseStorage

let storage = Storage.storage()

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: K.armListReusableCell, for: indexPath) as! MyTableViewCell

        let imagePath: String = "your imagePath"
        storageImageURL(imagePath) { (urlString) in
                    let url = URL(string: urlString)!
                    cell.imageView.af.setImage(withURL: url)
        }
        
        return cell
    }

func storageImageURL(_ imagePath: String, completion: @escaping (String) -> Void){
        let storageRef = storage.reference(forURL: "yourStorageURL")
        var returnURL = imagePath
        let imageRef = storageRef.child(imagePath)
        imageRef.downloadURL { url, error in
          if let error = error {
            print("\(error)")
          } else {
            returnURL = url?.absoluteString as! String
            completion(returnURL)
          }
        }
    }

つまり,cloud storageからのダウンロードが成功した時にcompletion(returnURL)を実行することで今回の場合ですとcell.imageView.af.setImage(withURL: url)が画像のダウンロードURLが確定してから実行できるようになります.

そのため,少し時間はかかりますがこれによってTableViewを先に表示したまま画像のダウンロードURLが確保できしだい画像がしっかりと表示されるようになります.

まとめ

というわけでこの記事ではCloud Storageにアップロードした画像をダウンロードしてTableView内のimageViewに表示する方法について解説しました.今までcompletionがよく分からなくて避けていたのですが応用するとこんなに便利なことまでできるのかと驚くばかりです.

というわけでcloud storageの活用を考えているみなさんも是非試してみてください.

0 件のコメント :

コメントを投稿