[Swift]QiitaのAPIを叩いて記事を取得して表示するサンプルアプリを書いてみた その2


##概要

[[Swift]QiitaのAPIを叩いて記事を取得して表示するサンプルアプリを書いてみた](http://qiita.com/BlackCat/items/0f5313b5a60ca39d0b12)の続き。

> 非同期処理の終了を呼び出し元で判断する方法がわからず、Notificationで書いてしまった。

これ、すっきりしなくてずっともやもやしてたので、上司に聞いてみた。
「クロージャが一番簡単だと思うよー」とさくっと言われてしまったので、クロージャにチャレンジ。

ついでに、SwiftyJSONの書き方もなんかしっくりこなかったので、JSONをモデルクラスにマッピングできるObjectMapperに乗りかえた。

##モデルクラスを実装

前回版と同じ結果になるようにtitleとuserIdをプロパティにもつモデルクラスItemを実装。
ネストされたJSONの値はuser.idといったように、ドットシンタックスでつなげればいいらしい。
拡張もしやすいし、モデルクラスのほうが好き。

```swift:Item
import Foundation
import ObjectMapper

struct Item: Mappable {
    var title: String?
    var userId: String?
    
    init?(_ map: Map){}
    
    mutating func mapping(map: Map) {
        title  <- map["title"]
        userId <- map["user.id"]
    }
}
```

##APIClientの仕様を変更

戻り値をクロージャで渡すようにしつつ、戻り値をモデルクラスにマッピングするように修正。
クロージャが全然わからなくて苦しんだけど、こっちのほうがすっきりしてて好きなので満足。
エラーもクロージャで渡したほうがいいかなぁ。

```swift:APIClient
import Alamofire
import ObjectMapper

class APIClient {

    func getAllItems(success: (([Item]) -> Void)) {
        let urlString: String = "https://qiita.com/api/v2/items"

        Alamofire.request(.GET, urlString)
            .responseJSON { response in
                switch response.result {
                case .Success(let value):
                    if let items = value as? NSArray {
                        var resultItems: [Item] = []
                        for item in items {
                            if item as? NSDictionary != nil {
                                resultItems.append(Mapper<Item>().map(item)!)
                            }
                        }
                        success(resultItems)
                    }

                case .Failure(let error):
                    print(error)
                }
        }
    }
}
```

あ、`resultItems.append(Mapper<Item>().map(item)!)`の部分だけど、プロパティ変数にappendしたらnilにしかならなかったので、ローカル変数で対応した。
ここもかなりハマった…。

##ViewControllerの仕様を変更

ここは特に説明なしでいいかな。

```swift:ViewController
class ArticleListViewController: UIViewController, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!
    var items: [Item] = []
    let client = APIClient()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "新着記事"
        tableView.dataSource = self

        client.getAllItems() { resultItems in
            self.items = resultItems
            self.tableView.reloadData()
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell")
        let item = items[indexPath.row]
        if let title = item.title {
            cell.textLabel?.text = title
        }
        if let userId = item.userId {
            cell.detailTextLabel?.text = userId
        }
        return cell
    }
}
```

##ソースコード

Githubにあげました。
https://github.com/macneko-ayu/SwiftPractice/tree/master/QiitaAPISample

##まとめ

オプショナルの扱い、めんどくさい。