SwiftでQiitaのAPIを表示させる。

##背景
iOSのアプリ設計で復習したいと思いに、Qiitaの記事を表示させるアプリを作成しようと思いました。この記事ではAPIからデータを取ってきて表示させるまでを書いていきたいと思います。このアプリで学んだことをいくつかに分けて説明していきますので次回記事が出来次第リンク先を載せます。

### 完成図
<img width="414" alt="IMG_995E08A268F6-1 (1).jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122719/6053b1e3-746f-b3cc-629f-b92e883829f6.jpeg">

## APIからデータを取得する
Qiitaが提供してくれているAPIを使用します。　
[APIのリンク先](https://qiita.com/api/v2/docs)


今回は作成日時から50個をQiitaが提供しているAPIから取得してみたいと思います。
なので下記の箇所を使用したいと思います。


```json
GET /api/v2/items
記事の一覧を作成日時の降順で返します。

per_page
1ページあたりに含まれる要素数 (1から100まで)
Example: 20
Type: string
Pattern: /^[0-9]+$/
```

```json

[
  {
    "rendered_body": "<h1>Example</h1>",
    "body": "# Example",
    "coediting": false,
    "comments_count": 100,
    "created_at": "2000-01-01T00:00:00+00:00",
    "group": {
      "created_at": "2000-01-01T00:00:00+00:00",
      "id": 1,
      "name": "Dev",
      "private": false,
      "updated_at": "2000-01-01T00:00:00+00:00",
      "url_name": "dev"
    },
    "id": "4bd431809afb1bb99e4f",
    "likes_count": 100,
    "private": false,
    "reactions_count": 100,
    "tags": [
      {
        "name": "Ruby",
        "versions": [
          "0.0.1"
        ]
      }
    ],
    "title": "Example title",
    "updated_at": "2000-01-01T00:00:00+00:00",
    "url": "https://qiita.com/yaotti/items/4bd431809afb1bb99e4f",
    "user": {
      "description": "Hello, world.",
      "facebook_id": "yaotti",
      "followees_count": 100,
      "followers_count": 200,
      "github_login_name": "yaotti",
      "id": "yaotti",
      "items_count": 300,
      "linkedin_id": "yaotti",
      "location": "Tokyo, Japan",
      "name": "Hiroshige Umino",
      "organization": "Increments Inc",
      "permanent_id": 1,
      "profile_image_url": "https://si0.twimg.com/profile_images/2309761038/1ijg13pfs0dg84sk2y0h_normal.jpeg",
      "team_only": false,
      "twitter_screen_name": "yaotti",
      "website_url": "http://yaotti.hatenablog.com"
    },
    "page_views_count": 100
  }
]
```

### Codableを使ってJSONを変換させる
API通信でデータを取得する際に、JSONで受け取ってモデルや構造体に変換する手法が一般的です。swiftyjsonなどを用いてパースしてjsonの値を取ってきたりしていました。Swift4からはswiftが提供したCodableを使うことでライブラリを使わずシンプルに記述できるようになりました。
今回はそちらのCodableを使っていきます。

使い方は下記の記事を参考にしました。
[Swift4 Codableがすごすぎた件]
(https://qiita.com/UJIPOID/items/2c436a80f1167f7bcac0)

今回は上記のQiitaApiから記事のタイトルとユーザー名を取得しました。

```swift
struct QiitaStruct: Codable {
    var title: String
    var user: User
    struct User: Codable {
        var name: String
    }
}
```

### APIをURLSessionを使って叩く
connpassAPIを叩くためにURLSessionを使いました。
URLSessionとはリクエストを受けて通信を行うクラスです。
またURLQueryItemを使うことでURLのクエリストリングを追加して、ページの要素数を50までと指定しました。

>例）"https://qiita.com/api/v2/items" -> "https://qiita.com/api/v2/items?per_page=50"

```swift

class QiitaViewModel {
    static func fetchArticle(completion: @escaping ([QiitaStruct]) -> Swift.Void) {

        let url = "https://qiita.com/api/v2/items"

        guard var urlComponents = URLComponents(string: url) else {
            return
        }

        urlComponents.queryItems = [
            URLQueryItem(name: "per_page", value: "50"),
        ]

        let task = URLSession.shared.dataTask(with: urlComponents.url!) { data, response, error in

            guard let jsonData = data else {
                return
            }

            do {
                let articles = try JSONDecoder().decode([QiitaStruct].self, from: jsonData)
                completion(articles)
            } catch {
                print(error.localizedDescription)
            }
        }
        task.resume()
    }
}
```


## tableviewにデータを表示させる

今回はextensionを使いクラスに定義を追加しました。
拡張先ではclassで`QiitaStruct`で取ってきた値を`article`に格納してそれを使いcellに代入する処理をしています。

```swift

extension QiitaViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell")
        let article = articles[indexPath.row]
        cell.textLabel?.text = article.title
        cell.detailTextLabel?.text = article.user.name
        return cell
    }

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

}
```

##　全体的なコード
コードは下記になります。

```swift

struct QiitaStruct: Codable {
    var title: String
    var user: User
    struct User: Codable {
        var name: String
    }
}


class QiitaViewModel {
    static func fetchArticle(completion: @escaping ([QiitaStruct]) -> Swift.Void) {

        let url = "https://qiita.com/api/v2/items"

        guard var urlComponents = URLComponents(string: url) else {
            return
        }

        urlComponents.queryItems = [
            URLQueryItem(name: "per_page", value: "50"),
        ]

        let task = URLSession.shared.dataTask(with: urlComponents.url!) { data, response, error in

            guard let jsonData = data else {
                return
            }

            do {
                let articles = try JSONDecoder().decode([QiitaStruct].self, from: jsonData)
                completion(articles)
            } catch {
                print(error.localizedDescription)
            }
        }
        task.resume()
    }
}
class QiitaViewController: UIViewController {
    private var tableView = UITableView()
    fileprivate var articles: [QiitaStruct] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "QiitaAPI"
        
        tableView.dataSource = self
        tableView.frame = view.frame
        view.addSubview(tableView)
        QiitaViewModel.fetchArticle(completion: { (articles) in
            self.articles = articles
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        })
    }

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

extension QiitaViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell")
        let article = articles[indexPath.row]
        cell.textLabel?.text = article.title
        cell.detailTextLabel?.text = article.user.name
        return cell
    }

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

}
```


## 次にやること
次回はcellの大きさなどを変更していこうと思います。