前提
API通信について学習内容の整理も含め、今回記事にしてみようと思います。
内容については、GithubAPIからGithubのプロフィール情報を取得してアプリ内で表示するプロジェクトを作成し、その中でAPI通信について説明していければと思います。
また、サードパーティ製のライブラリは使わずに、Foundationでの実装となります。
対象者
- Swiftの基礎文法について理解している方
- 通信処理について学んだことがない方
API通信の流れ
-
URLの構築
-
URLRequestの作成
-
タスクを生成し実行
-
レスポンスを受け取る
-
データをデコードする
1. URLの構築
まずは、サーバーから情報を取得するためのURLを定義する必要があります。
GithubのAPIを使ってユーザー情報を取得してみましょう。
この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. タスクを生成し実行
URLSession
のdataTaskメソッド
を使ってURLにアクセスし、レスポンスを取得します。
let task = URLSession.shared.dataTask(with: reqest, completionHandler:{ data, response, error in }
URLSession
のdataTask
では引数として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通信を実装してみました。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
参考