【Swift】QiitaのAPI(v2)をiOSアプリで操作する方法!パラメータやクエリの実装

この記事からわかること

  • QiitaAPI(v2)で記事情報を取得する方法
  • Swiftで表示するiOSアプリ作り方
  • 受け取れるJSON形式
  • パラメータクエリ種類使い方

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

公式リファレンス:Qiita API v2

Qiitaの記事情報を表示するiOSアプリを開発してみたかったので実際に開発してみました。ちなみに以下記事ではAndroidアプリでQiitaの記事情報を表示するアプリを実装しています。

QiitaのAPI:Qiita API v2

Qiitaでは記事情報やユーザー情報をJSON形式の文字データとして取得できるように「Qiita API v2」というAPI(Application Programming Interface)が用意されています。このAPIは指定のURLにアクセスした際にJSON形式のデータを取得できるようになっており、任意のパラメータを指定することで取得するデータのフィルタリングや数をコントロールすることができるようになっています。

リクエストには制限があり、認証している状態ではユーザーごとに1時間に1000回まで、認証していない状態ではIPアドレスごとに1時間に60回までになっています。今回は認証をせずに実装していきます。

API URL

アクセスするのはhttps://qiita.com/api/v2で始まるURLです。それ以降にitemsusers、パラメータなどを指定することで任意のデータを取得することができるようになります。

記事(1つ):https://qiita.com/api/v2/items/<記事ID>

例えば上記のURLにアクセスするとQiitaに投稿されている「【SwiftUI】MVVM構造でログイン機能を実装してみた」という記事の情報がJSON形式の文字列になった状態で取得することができます。記事IDはQiitaの記事にアクセスしたURLの末尾の数字の羅列です。

【Swift】QiitaのAPIで記事情報を取得して表示するアプリを開発してみた!

ちなみに<記事ID>を指定しない場合Qiitaの全ての記事(新着順20個)が受け取れるようです。

記事(新着順20個):https://qiita.com/api/v2/items

受け取れるJSON形式

受け取れるJSON形式には記事情報だけでなく、様々な情報が組み込まれているため必要となる情報のみを抽出する必要があります。必要になりそうなJSON形式は以下のようになります。

[{
  "id": "記事の一意のID",
  "title": "記事のタイトル",
  "body": "記事の本文",
  "created_at": "記事の作成日時",
  "updated_at": "記事の更新日時",
  "user": {
    "id": "ユーザーの一意のID",
    "name": "ユーザー名",
    "profile_image_url": "ユーザーのプロフィール画像のURL"
  },
  // .....他にもさまざまな情報
}]

それ以外にもtagやいいね数、コメント数、参照URLなどがキーと値に割り振られて受け取ることができます。

JSONDecoderで変換する用のモデル構造体を定義

JSON形式で取得した記事情報をSwift内で操作するために構造体へと変換していきます。そのために変換対象となるUser構造体とArticle構造体を定義しておきます。

struct User : Decodable{
    let id:String
    let name:String
    let profile_image_url:String
}

struct Article : Decodable{
    let id:String
    let title:String
    let body:String
    let created_at:String
    let updated_at:String
    let user:User
}

ここでは各プロパティ名をJSONのキーと一致するように命名することとDecodableプロトコル(またはCodable)への準拠が必要になります。

AlamofireでHTTP通信の実装

APIへのリクエスト処理はHTTPネットワーキングライブラリ「Alamofire」を使用していきます。

import UIKit
import Alamofire

class QiitaApiModel {

  public func fetchArticles(completion:@escaping ([Article]) -> Void) {

      AF.request("https://qiita.com/api/v2/items")
          .responseData { response in
              do {
                  let decoder = JSONDecoder()
                  let articles = try! decoder.decode([Article].self, from: response.data!)
                  print(articles)
                  completion(articles)
              } catch {
                  print(error.localizedDescription)
              }
          }   
  }
}

上記の例ではhttps://qiita.com/api/v2/items(全記事)を取得してるので[Article].selfになります。

あとはUIを調整して配置すれば以下のようにQiitaの記事を取得して表示させることができます。下にコードを載せておきます。

【Swift】QiitaのAPIで記事情報を取得して表示するアプリを開発してみた!

記事情報配列を観測するViewModel

class QiitaArticleViewModel:ObservableObject {
    
    static let shared = QiitaArticleViewModel()
    
    private let model = QiitaApiModel()
 
    @Published  var articles: [Article] = []
    
    func setArticle(){
        model.fetchArticles { array in
            self.articles = array
        }
    }
}

Qiita日付調整用ViewModel

class DisplayDateViewModel {
    
    private let df = DateFormatter()
    
    public func getQiitaFormatToDate(str:String) -> String{
        df.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
        let date = df.date(from: str)!
        df.dateFormat = "yyyy/MM/dd HH:mm"
        return df.string(from: date)
    }

}

Qiita記事表示用View(Swift UI)

struct ContentView: View {
    
    @ObservedObject  var qiitaArticleVM = QiitaArticleViewModel.shared
    private let displayDateVM = DisplayDateViewModel()
    
    var body: some View {
        VStack{
            
            List(qiitaArticleVM.articles){ article in
                
                HStack{
                    AsyncImage(url: URL(string: article.user.profile_image_url)) { image in
                        image.resizable()
                    } placeholder: {
                        ProgressView()
                    }.frame(width: 30, height: 30)
                    VStack{
                        Text(article.title)
                        HStack{
                            Spacer()
                            Text(displayDateVM.getQiitaFormatToDate(str: article.created_at))
                        }
                    }
                }
            }
            Button {
                qiitaArticleVM.setArticle()
            } label: {
                Text("Button")
            }
        }
    }
}

リクエストにパラメータやクエリを追加する

記事情報を取得できるURLに対してパラメータを渡すことで取得するページ番号などを指定することが可能です。

パラメータ 概要
page 表示するページ番号(初期値:1/最大値:100)
per_page 1ページに対して含ませる記事数(初期値:20/最大値:100)
query 検索クエリ

パラメータはURLの末尾に?を追加し、複数のパラメータを指定する際は&で連結していきます。

全記事を2個でページングした際の1ページ目

検索クエリで条件を絞る

queryパラメータの後にはさまざまな項目を指定することで条件にマッチした記事情報だけに絞った結果を取得することが可能です。?query=の後にクエリ項目:値という形式で指定します。

タイトルに「swift」が含まれる記事

クエリ項目 概要
title タイトルに指定の文字列が含まれる
body 本文に指定の文字列が含まれる
tag 指定のタグを持つ
-tag 指定のタグを持たない
user 指定のユーザー
created 作成日
updated 更新日
stocks ストック件数

URLの有効性をチェックする

クエリに渡す文字に日本語が含まれる場合は適切なエンコードをしないと正常に動作しません。またそれ以外にもURL自体が有効であるかどうかをチェックすることでエラーを起こすことなくリクエストを送信することができるようになります。

let url = "https://qiita.com/api/v2/items?page=1&per_page=5&query=title:日本語"

URL(string: url) // nil

上記のままではうまく変換できず、無効なURLになってしまうのでaddingPercentEncodingを使用してエンコードする必要がある。

let url = "https://qiita.com/api/v2/items?page=1&per_page=5&query=title:"
let text = "日本語"
let encodeString = text.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!

URL(string: url + encodeString)! // https://qiita.com/api/v2/items?page=1&per_page=5&query=title:%E6%97%A5%E6%9C%AC%E8%AA%9E

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index