[swift]挫折しながら覚えるiOS開発その4 API通信


前回、カスタムセルの実装を行いました。

前回は表示するデータがダミーデータだったので、今回は実際にAPIからデータを取得し、取得したデータを表示するように起動時に呼び出されるsetupLinksメソッドを書き換えてみます。

1. Alamofireを使えるようにする

「swiftでHTTP通信をするならAlamofireを使うのがスタンダード」というアドバイスをいただいたので、まずはAlamofireを使えるようにします。

iOS開発では、cocoapodsを使ってライブラリ管理を行うのが一般的のようですね。

cocoapodsインストールのため、一旦xcodeを終了します。

続いてターミナルからcocoapodsのインストール。

その後、プロジェクトルートに移動してPodfileを作成します。

gem install cocoapods
pod setup
cd [.xcodeprojがある階層まで移動]
vi Podfile

Podfile内に使用するライブラリを記述。

公式ドキュメントに記載されていた内容で保存します。

# Podfile

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!

pod 'Alamofire', '~> 1.2'

pod installでAlamofireのインストールを行います。

pod install

インストールが完了するとプロジェクトルートに「アプリ名.xcworkspace」というファイルが作成されているので開きます。

Podsプロジェクト内にAlamofireが追加されているのが確認できます。

ios4-1

最後にプロジェクト内でAlamofireが使えるように、ライブラリの追加を行います。

プロジェクト設定画面の一番下にある「Linked Frameworks and Libraries」の「+」を選択し、Alamofireを追加します。

ios4-2

これで、「import Alamofire」とすれば、そのクラスでAlamofireが使えるようになります。

2. API通信してみる

以前作成したQiitaのストックランキング取得APIをパースして表示できるようにしてみます。

swiftはjsonの扱いが大変とのことだったので、swift-jsonを使わせていただきました。

インストール方法としては以下のファイルをプロジェクト内に保存すれば使用可能になります。

dankogai/swift-json

後から気づいたのですが、今回Alamofireでjsonを取得してからswift-jsonでパースすることにしましたが、swift-jsonはurl経由での読み込みにも対応していたのでAlamofireを使わなくてもAPI通信は可能だったようです。

試行錯誤しながら取得したjsonをループでLinkモデルに追加するようにして、最終的なViewControllerは以下のようになりました。

import UIKit
import Alamofire // 追加

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.setupLinks()

        tableView.delegate = self
        tableView.dataSource = self
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    var links = [Link]()

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return links.count
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell: LinkViewCell = tableView.dequeueReusableCellWithIdentifier("LinkViewCell") as! LinkViewCell
        println(cell)

        cell.setCell(links[indexPath.row])
        return cell
    }

    // apiからデータを取得するように変更
    func setupLinks() {
        Alamofire.request(.GET, "http://qiita-stock.info/api.json")
            .responseJSON { _, _, data, _ in
                var json = JSON(data!)
                for (i, topic) in json {
                    println(topic["send_date"].asString)
                    for (k, link) in topic["links"] {
                        self.links.append(Link(
                            title: link["title"].asString!,
                            username: link["author"].asString!,
                            userIconUrl: link["icon"].asString!,
                            stockCount: link["stock"].asInt!
                        ))
                    }
                }
                // TableViewの更新
                self.tableView.reloadData()
        }
    }
}

この状態でシミュレータを起動すると、しばらく待った後、以下のようにAPIから取得したデータが表示されるようになりました。

ios4-3

ただ、タイトル文字がはみ出していたり、ストック数の表示が切れていたりレイアウトの修正が色々必要そうです。

また、スクロールしようとすると非常に動作が重いので原因を調べる必要があります。

あとは現状だと毎回APIにアクセスしてしまっているため、一度取得した結果をキャッシュするようにしてWebサーバへの負荷を減らしたいです。

このように課題が色々見つかりましたが、とりあえずAPI通信できるところまでできました。

次回は上記の課題を調査し、解決していきたいと思います。

参考