LoginSignup
30

More than 3 years have passed since last update.

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

Posted at

背景

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

完成図

IMG_995E08A268F6-1 (1).jpeg

APIからデータを取得する

Qiitaが提供してくれているAPIを使用します。 
APIのリンク先

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

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

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

[
  {
    "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がすごすぎた件

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

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"


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に代入する処理をしています。


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
    }

}

 全体的なコード

コードは下記になります。


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の大きさなどを変更していこうと思います。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30