SwiftでAPIを叩いてQiita記事をTableViewに表示しよう！

# この記事について 

　この記事は、Swiftを勉強していて「アプリの幅を広げたい！」「APIとか叩いて多くの情報を扱いたい！」という人に向けての記事です。　

# もくじ
0. やること
1. 完成予想図
2. ViewController　-API叩いて情報取得-
3. ViewController　-tableViewに表示-
4. おわりに


# 1.　やること
　APIを利用するときは、 AlamofireやSwiftyJSONなどのライブラリを用いたり、Codableを使用することが多いですが、今回はAPIを叩いてJson型の情報を取得後Jsonをパースして表示するところまでやります。
　
　取得する情報としては、僕がSwiftを勉強するときにお世話になった[まっすーさんのQiita記事のタイトル](https://qiita.com/masuhara)にします。



# 2.　完成予想図
![スクリーンショット 2019-10-21 15.18.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373532/9f2bfa01-7e0a-f2dd-6ede-ca9cae4d95de.png)




# 3.　ViewController　-API叩いて情報取得-

　APIを叩いて情報を取得し、それをパースしてタイトルだけ抜き出し配列に保存することを、getQiitaTitle()　としました。

```swift:ViewController
func getQiitaTitle() {
        
        
        // (A) リクエストURL指定
        let url: URL = URL(string: "https://qiita.com/api/v2/items?page=1&query=user%3Amasuhara")!
        
        // (B) URLSessionを用いてリクエスト
        let task: URLSessionTask = URLSession.shared.dataTask(with: url, completionHandler: {data, response, error in
            
            do {
                // (C) JSONに変換するためのメソッド
                let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) as! [Any]
                // (D) Any型の配列に変換したものを、[String: Any]の辞書型にダウンキャスト
                let articles = json.map { (article) -> [String: Any] in
                    return article as! [String: Any]
                }
                
                // (E) 記事の総数をcountと定義する
                let count = articles.count
                
                // (F) for文で各記事のtitleを抜き出し、titleArray配列に追加
                for i in 0...count-1 {
                    let title = articles[i]["title"] as! String
                    self.titleArray.append(title)
                }
                
                // (G)　TableView更新
                DispatchQueue.main.sync {
                    self.tableView.reloadData()
                }
                
            }
            catch {
                print(error)
            }
        })
       
        task.resume()
        
    }

```

一つずつ見てきます。






 (A) 　

```Swift:ViewController
        // (A) リクエストURL指定
        let url: URL = URL(string: "https://qiita.com/api/v2/items?page=1&query=user%3Amasuhara")!
```

　まず、QiitaAPIの[ドキュメント](https://qiita.com/api/v2/docs)を参考にして、取得したいデータをURLで指定します。URL指定する際、いくつかの文字はエンコードする必要がありますので、[この記事](https://www.seil.jp/doc/index.html#tool/url-encode.html)を読んでみてください！




 (B) 

```Swift:ViewController
        // (B) URLSessionを用いてリクエスト
        let task: URLSessionTask = URLSession.shared.dataTask(with: url, completionHandler: {data, response, error in
            
            do {
            
          
            }
            catch {
                print(error)
            }
        })
```

　URLで指定したデータをリクエストします。HTTPからはじまるURLや、HTTPSからはじまるURLを、ブラウザ上で叩いて呼び出すことを「リクエスト」、リクエストを受けたサーバがそれをもとに返すデータのことを「レスポンス」といいます。do-catch文を用いて分岐させています。




 (C) 

```Swift:ViewController
 // (C) JSONに変換するためのメソッド
    let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) as! [Any]
```

　レスポンスをJsonに変換するためのメソッドを実行したあと、パースしてAny型の配列にダウンキャストします。




 (D) 

```Swift:ViewCotroller
 // (D) Any型の配列に変換したものを、[String: Any]の辞書型にダウンキャスト
    let articles = json.map { (article) -> [String: Any] in
       return article as! [String: Any]
    }
```

　Any型にしたものを、[String:Any]の辞書型配列にして、KeyとValueが対応するようにします。これをすることによって、得たいデータ(今回であればtitle)を、Keyを指定することによって得ることができます。




 (E) 

```Swift:ViewController
  // (E) 記事の総数をcountと定義する
    let count = articles.count
```

　各記事のタイトルを、for文を用いて取得したいので、前記事の総数をcountと定義します。





 (F) 

```Swift:ViewController
// (F) for文で各記事のtitleを抜き出し、titleArray配列に追加
  for i in 0...count-1 {
     let title = articles[i]["title"] as! String
     self.titleArray.append(title)
   }
```

　For文を用いて、各記事の”title"キーを指定してタイトルの情報を取得し、これはAny型なのでString型にダウンキャストします。それを、事前に定義したString型の空配列titleArrayに追加していきます。





 (G)　

```Swift:ViewController
   // (G) TableView更新
  DispatchQueue.main.sync {
      self.tableView.reloadData()
  }
```

　ここまでで完了かと思いきや、それだけだとtableViewに何も表示されません。これは同期処理や非同期処理などの扱いになり、やや難なのでここでは省きます。ここでは、[この記事](http://takayukinakata.hatenablog.com/entry/2018/05/25/193356)を参考にしてtableViewの更新を行いました。


# 4.　ViewController　-tableViewに表示-

　tableViewのDataSourceメソッドは以下の通りです。


```swift:ViewCotroller
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //cellの数
        return titleArray.count
        
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
        //titleArayはAny型の配列なのでString型にダウンキャストする
        cell.textLabel?.text = (titleArray[indexPath.row] )
       
        return cell
    }
```






# 4.　おわりに
　WebAPIを使えば、アプリの幅が圧倒的に広がります。（WetherAPIを用いて天気情報を取得したり、じゃらんAPIを使えば宿泊情報をアプリに組み込めたり......。）
実際使用するときは、Codableやライブラリを使ったほうが、扱いやすいと思われます。

以下の記事はQiitaの記事をCodableを使用してTableVieｗに表示する方法です。

https://qiita.com/YukiNagai1016/items/fb3a7a3b07fbf27a3675



 また、作成したQiitaAPIのサンプルプロジェクトは以下のGithubページからクローンできます。

https://github.com/ritsuyasaito/practiceQiitaAPI