3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

API通信について理解する

Last updated at Posted at 2023-08-23

前提

API通信について学習内容の整理も含め、今回記事にしてみようと思います。

内容については、GithubAPIからGithubのプロフィール情報を取得してアプリ内で表示するプロジェクトを作成し、その中でAPI通信について説明していければと思います。

また、サードパーティ製のライブラリは使わずに、Foundationでの実装となります。

対象者

  • Swiftの基礎文法について理解している方
  • 通信処理について学んだことがない方

API通信の流れ

  1. URLの構築

  2. URLRequestの作成

  3. タスクを生成し実行

  4. レスポンスを受け取る

  5. データをデコードする

1. URLの構築

まずは、サーバーから情報を取得するためのURLを定義する必要があります。
GithubのAPIを使ってユーザー情報を取得してみましょう。

https://api.github.com/users/ユーザー名

このURLにユーザー名を入力してネット上で検索してみると、

{
    "login": "ユーザー名",
    "id": 214322498,
    "node_id": "U_kgDOBsEp7g",
    "avatar_url": "https://avatars.githubusercontent.com/u/853352418?v=4",
    "gravatar_id": "",
    "url": "https://api.github.com/users/ユーザー名",
    "html_url": "https://github.com/ユーザー名",
    "followers_url": "https://api.github.com/users/ユーザー名/followers",

    ~~(以下略)~~
}

こんな感じで値が返ってくると思います。
これが今回API通信でサーバー上から取得したい値となります。

2. URLRequestの作成

まずは、URLを格納する定数を定義しましょう。

let url = URL(string: "https://api.github.com/users/ユーザー名")

リクエストを送る際は、このURLをURLRequest型に変換してあげる必要があります。

let request = URLRequest(url)

HTTPリクエストはURLRequestクラスを使って構築します。
生成されたリクエストにはHTTPメソッド(postやgetなど)やヘッダーなどのパラメータを付与することができます。

HTTPメソッドを変更する場合

HTTPメソッドを変更したい場合は、httpMethodプロパティにメソッドを文字列型で渡します。
デフォルトでは、「GET」に設定されています。

request.httpMethod = "POST"

3. タスクを生成し実行

URLSessiondataTaskメソッドを使ってURLにアクセスし、レスポンスを取得します。

let task = URLSession.shared.dataTask(with: reqest, completionHandler:{ data, response, error in }

URLSessiondataTaskでは引数としてURLRequest型のURLと、クロージャとしてcompletionHandlerを受け取ります。

completionHandlerから受け取る値として、 それぞれdata, response, errorを引数として受け取ります。

生成したタスクを実行する

URLSessionDataTaskはインスタンス化しただけだと実行されないので、resume()メソッドを使って実行します。

task.resume()

4. レスポンスを受け取る

dataTaskの処理の流れとして簡単に解説すると、

dataTask(with: reqest,completionHandler:{ data, response, error in }

1つ目の引数にURLを渡しサーバー通信が終わると、
2つ目の引数「completionHandler」というクロージャに

  • dataにはサーバーから返されたデータ
  • responseにはHTTPヘッダーやステータスコードなど
  • errorにはリクエスト失敗時の理由

が渡されます。

completionHandler」は簡単に言うと、通信が終了した後の完了処理をするためのクロージャです。

また、この3つの値は全てオプショナル型であるため、nilが許容されています。

  • データ取得成功時:
    dataに値が入り、errorにはnilが入る

  • データ取得失敗時:
    errorに値が入り、dataにはnilが入る

URLSessionは、サーバ通信が終わると、このcompletionHandlerの引数にレスポンスとして値が入るという処理の流れになります。

5. データをデコードする

取得したAPIデータをプロジェクト内で使用できるようにしてあげるには、デコードする必要があります。
今回はユーザー名、プロフィール画像、ユーザーIDを取得するとしてみましょう。
まず、JSON Decodeのための構造体を用意する必要があります。

//プロフィール情報
struct User: Decodable {
    let name: String
    let id: Int
    let avatarURL: URL

    enum CodingKeys: String, CodingKey {
        case name = "name"
        case id = "id"
        case avatarURL = "avatar_url"
    }
}

次に受け取ったデータを、JSONDecoder() を使って User オブジェクトにデコードしていきます。

let user: User = try JSONDecoder().decode(User.self, from: data)

JSONDecoderを使うと、try-catch構文を使用する必要が出てきますが、今回説明は省略します。
簡単に説明するとエラー発生時に、適切にエラー処理をしてくれる構文という認識でOKかと思います

ここまででAPI通信を実行し、Githubからプロフィール情報を取得してくる処理は完成です。
ここからは、取得したプロフィール情報をUIに表示していく処理になります

今回実装したサンプルコード

import UIKit
import Foundation

//プロフィール情報
struct User: Decodable {
    let name: String
    let id: Int
    let avatarURL: String

    enum CodingKeys: String, CodingKey {
        case name = "name"
        case id = "id"
        case avatarURL = "avatar_url"
    }

}

class ViewController: UIViewController {

    @IBOutlet weak var avatarImage: UIImageView!
    
    @IBOutlet weak var name: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        getGithubAPI()
    }

    func getGithubAPI() {
        guard let url = URL(string: "https://api.github.com/users/Githubのユーザー名") else { return }
        let reqest = URLRequest(url: url)

        let task = URLSession.shared.dataTask(with: reqest, completionHandler: { data, response, error in
            if let err = error {
                print("error: \(error)")
                return
            }
            guard let data = data else { return }
            do {
                let user: User = try JSONDecoder().decode(User.self, from: data)
                //UIの処理はメインスレッドで実行
                DispatchQueue.main.async {
                    self.name.text = user.name
                    //文字列として保持されているavatarURLから画像を取得する
                    if let avatarURL = URL(string: user.avatarURL) {
                        URLSession.shared.dataTask(with: avatarURL) { data, response, error in
                            if let data = data {
                                DispatchQueue.main.async {
                                    self.avatarImage.image = UIImage(data: data)
                                }
                            }
                        }.resume()
                    }
                }
                print(user)
            } catch let err {
                print("error: \(err)")
            }
        })
        task.resume()
    }

最後に

ご覧いただきありがとうございました。
今回は簡易的にAPI通信を実装してみました。

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

参考

3
4
0

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
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?