Swift製のURL画像取得ライブラリAlamofireImageを使って商品一覧画面を作成してみた

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは!モバイルアプリ開発部の田中孝明です。

商品一覧を表示するようなiOSアプリ作成を作成する場合、「商品画像」+「商品名」のように画像を表示させる仕様があったとします。

商品一覧を取得するAPIの結果を受け取った際、画像の場合はURLという設計が多いと思います。
画像を表示するタイミングで別途取得させるようになっています。

よくあるJSONのレスポンスの例:

{
    "item" = [
        {
            "name": "Item name",
            "description": "Item description.",
            "image_url": "http://xxx.xxxx.png"
        },
        {
            ...

そこで今回使用しようと模索したのがAlamofireImageです。
Swiftのネットワークライブラリとして有名なAlamofireを開発しているチームが画像取得用に開発したライブラリです。

Podfileの設定

AlamofireImageCocoaPodsを使用してプロジェクトに組み込みます。

platform :ios, '8.0'
use_frameworks!
pod 'AlamofireImage'

あとはインストールをすればプロジェクトに組み込まれます。

$ pod install

以上でプロジェクトにAlamofireImageが組み込まれます。

使用方法

URLから画像取得を行いたいクラスにAlamofireImageをインポートします

import AlamofireImage

あとはUIImageViewaf_setImageWithURLというメソッドが拡張されていますので、これをコールします。
それぞれの引数には指定した画像のURLと、取得中に表示する一時的な画像をセットします。

func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) {
    let item = self.items?[indexPath.row]

    if let smallImageURL = item?.smallImageURL {
        let URL = NSURL(string: smallImageURL)!
        cell.imageView!.af_setImageWithURL(
            URL,
            placeholderImage: UIImage(named: "no-image")
        )
    }

    cell.textLabel!.text = item?.name ?? "No title"
    cell.detailTextLabel!.text = item?.description ?? "No description"
}

以上でURLで画像を取得完了後に自動で画像が表示されるようになります。

また内部で取得した画像をキャッシュする機構が働いています。
再度表示する際にわざわざURLアクセスをせず、キャッシュに保存している画像を表示できます。
上記のメソッドを呼ぶだけでキャッシュの管理も行ってくれますので非常に便利です!

キャッシュに保存した画像については最終アクセス日が古い順番に自動で削除されます。

サンプル

今回試しにYahooショッピング様の商品検索APIを使用し、商品一覧をUITableViewで表示させた後に商品画像をURL経由で非同期に取得するようにしてみました。

デベロッパー登録が必要ですが、そちらの方法は割愛させていただきます。

CocoaPodsで他に必要なライブラリをインストールします。

pod 'Alamofire'
pod 'SwiftyJSON

あとはUIRefreshControlを実装し、UITableViewをPullした時に商品検索APIが呼ばれるようにしました。

self.refreshControl = UIRefreshControl()
self.refreshControl?.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)

Alamofireでrequestを送り、responseに返ってきた結果をparseします。

func refresh(sender: AnyObject) {
    let parameters = [
        "appid"      : applicationID,
        "category_id": "635",
        "sort"       : "-sold"
    ]
    Alamofire.request(.GET, "\(apiEndpoint)/itemSearch", parameters: parameters)
        .responseJSON { response in
            jsonParse: do {
                var items: [Item] = []

                switch response.result {
                case .Success(let value) :
                    let json = JSON(value)

                    guard let resultSet = json["ResultSet"].dictionary else {
                        break jsonParse
                    }

                    guard let totalResultsReturned = resultSet["totalResultsReturned"]?.intValue else {
                        break jsonParse
                    }

                    guard let resultsOfOnePage = resultSet["0"]?.dictionary else {
                        break jsonParse
                    }

                    guard let results = resultsOfOnePage["Result"]?.dictionary else {
                        break jsonParse
                    }

                    for num in 0..<totalResultsReturned {

                        guard let result = results["\(num)"] else {
                            continue
                        }

                        let name           = result["Name"].string ?? ""
                        let description    = result["Description"].string ?? ""
                        let headline       = result["Headline"].string ?? ""
                        let code           = result["Code"].string ?? ""
                        let smallImageURL  = result["Image"]["Small"].string ?? ""
                        let mediumImageURL = result["Image"]["Medium"].string ?? ""

                        let item = Item(
                            name: name,
                            description: description,
                            headline: headline,
                            code: code,
                            smallImageURL: smallImageURL,
                            mediumImageURL: mediumImageURL)

                        items.append(item)
                    }
                case .Failure(let error) :
                    print("error: \(error)")
                }
                self.items = items
                self.tableView?.reloadData()
            }
            self.refreshControl?.endRefreshing()
    }
}

実行した結果は以下のようになります。

alamofireimage-ss

まとめ

プロダクトコードに組み込む際は諸々のチューニングは必要だとおもいますが、キャッシュ機構+非同期でURL画像の取得が簡単にできるので便利だと思います!