SwiftでWeb APIと通信する際に基本となるのが URLSession
です。
データの取得や送信、ファイルのダウンロードなど、インターネットとのやり取りには欠かせない仕組みです。
この記事では URLSession
の基本的な使い方から、活用シーン、非同期処理の扱い方、注意点までをわかりやすく丁寧に解説します。
URLSessionとは?
URLSession は、HTTP通信を行うためのApple標準のAPIです。
リクエストの送信、レスポンスの受信、データのダウンロード/アップロードなどを非同期で行うための基本的な枠組みを提供してくれます。
たとえば「サーバーからJSONを取得してアプリ内で使いたい」「画像を非同期で読み込みたい」といった場合には、URLSession が活躍します。
URLSessionの構文は非常にシンプルで、通信処理をすぐに始められるのが特徴です。
もっともよく使われるのは URLSession.shared
という共有セッションインスタンス。
これは標準的な設定(キャッシュ、タイムアウトなど)で用意された共通のセッションです。
たとえば:
このように shared
プロパティから始めるだけで、追加の設定なしにすぐ通信を開始できます。
dataTask
や downloadTask
などもこの shared
から直接呼び出せます。
一方で、より細かく制御したい場合は URLSession(configuration:)
を使って自分専用のセッションを作成することも可能です。
具体例①:GETリクエストでJSONを取得する基本的な使い方
まずは一番シンプルな「GETリクエストでデータを取得する」例を見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import Foundation let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")! let task = URLSession.shared.dataTask(with: url) { data, response, error in if let error = error { print("通信エラー:", error) return } guard let data = data else { print("データがありません") return } if let json = try? JSONSerialization.jsonObject(with: data) { print("受け取ったJSON:", json) } } task.resume() |
このコードの流れは以下の通りです:
- 通信先のURLを用意する
URLSession.shared.dataTask
を使って非同期通信を開始- 通信完了後、クロージャ内でエラーチェック・データ処理を行う
resume()
を呼んで通信開始
Swiftでは、.resume()
を忘れるとリクエストが送信されないため要注意です。
具体例②:POSTリクエストでデータを送信する
APIに対してデータを送るには URLRequest
を使ってHTTPメソッドやヘッダーを指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
var request = URLRequest(url: URL(string: "https://example.com/api/send")!) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") let parameters = ["name": "Taro", "age": 28] request.httpBody = try? JSONSerialization.data(withJSONObject: parameters) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("エラー:", error) return } if let data = data, let responseText = String(data: data, encoding: .utf8) { print("サーバーからの返答:", responseText) } } task.resume() |
このようにすれば、サーバーにJSON形式のデータを送信することができます。
URLSessionの主な機能
URLSession
が提供する機能は、大きく「各種タスクによる転送処理」と「デリゲート/設定によるふるまいの制御」に分かれます。
下の一覧は、日常的に使う中核APIを目的別にまとめたものです。
まずはここを押さえておくと、どの用途でどのタスクを選べばよいか判断しやすくなります。
機能 | 内容 |
---|---|
dataTask |
データ取得やAPI呼び出しに使用 |
downloadTask |
ファイルをダウンロードして一時ファイルに保存 |
uploadTask |
ファイルやデータをサーバーにアップロード |
delegate を使った通信管理 |
認証処理や進捗表示を細かく制御可能 |
URLSessionConfiguration |
タイムアウトやキャッシュなど、通信の基本設定を変更可能 |
非同期/async-awaitスタイルでの書き方
iOS15以降では、よりシンプルで可読性の高い async-await スタイルも使えます。
1 2 3 4 5 6 7 8 9 10 11 12 |
func fetchTodo() async { let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")! do { let (data, _) = try await URLSession.shared.data(from: url) let json = try JSONSerialization.jsonObject(with: data) print("JSON:", json) } catch { print("エラー:", error) } } |
非同期関数の中で await を使うことで、クロージャを使わずに直感的なコードが書けるようになりました。
補足:data(from:) / .data(for:)について
上の例で使っている URLSession.shared.data(from:)
や、URLRequest
を渡す URLSession.shared.data(for:)
は、従来の dataTask
を async/await 用に高レベルでラップしたAPI です。
どちらも resume()
は不要で、await
した時点で通信が開始され、(Data, URLResponse)
のタプルが返ります。
data(from: URL)
URL だけで完結する GET などに最適。簡潔に書けます。data(for: URLRequest)
メソッドやヘッダー、ボディを指定したいときはこちら。POST/PUT などで便利です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// 例:URLRequest を使った async POST func postUser() async throws { var req = URLRequest(url: URL(string: "https://example.com/api/users")!) req.httpMethod = "POST" req.setValue("application/json", forHTTPHeaderField: "Content-Type") req.httpBody = try JSONSerialization.data(withJSONObject: ["name": "Taro"]) let (data, response) = try await URLSession.shared.data(for: req) guard let http = response as? HTTPURLResponse, (200...299).contains(http.statusCode) else { throw URLError(.badServerResponse) } // 必要なら JSONDecoder でデコード // let user = try JSONDecoder().decode(User.self, from: data) } |
data(from:)
は手早い取得、data(for:)
は細かなリクエスト指定という使い分けが定番です。
どちらも戻り値の URLResponse
を HTTPURLResponse
にキャストして ステータスコードを検証するのを忘れないようにしましょう。
UI 更新はこれまでどおり メインスレッドで行います。
注意点
.resume() を忘れない(dataTask の場合)
dataTask
などを作成しただけでは通信は始まりません。
必ず .resume()
を呼ぶ必要があります。
1 2 3 |
let task = URLSession.shared.dataTask(with: url) // 通信が始まらない! |
これは初心者によくあるミスなので注意が必要です。
async/await の .data(...) では resume() 不要
URLSession.shared.data(from:)
や data(for:)
は、await
したタイミングで通信が開始されます。
resume()
は不要ですが、戻り値の (Data, URLResponse)
を必ず受け取り、レスポンスの検証を行いましょう。
1 2 3 |
let (data, response) = try await URLSession.shared.data(from: url) // resume() は不要 |
UIの更新はメインスレッドで行う
非同期通信のコールバックはバックグラウンドスレッドで実行されます。
そのため、UI更新は DispatchQueue.main.async
で囲う必要があります。
1 2 3 4 |
DispatchQueue.main.async { self.label.text = "取得完了" } |
async/await
を使う場合は、UIを触る関数・プロパティを @MainActor
にするのも安全です。
1 2 3 4 5 |
@MainActor func updateUI(text: String) { label.text = text } |
HTTPステータスコードの確認も忘れずに
サーバーからのレスポンスが200系(成功)であるかどうかも確認するのが一般的です。
1 2 3 4 |
if let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) { // OK } |
async/await
の場合も同様に、取得した URLResponse
を HTTPURLResponse
にキャストして検証します。
1 2 3 4 5 |
let (data, response) = try await URLSession.shared.data(from: url) guard let http = response as? HTTPURLResponse, (200...299).contains(http.statusCode) else { throw URLError(.badServerResponse) } |
まとめ
今回はSwiftでHTTP通信を行うための URLSession
について紹介しました。
URLSession
はデータ取得・送信のための非同期APIdataTask
,downloadTask
,uploadTask
などの機能がある.resume()
を忘れずに呼ぶ必要がある(async/await の .data(...) では不要)async-await
を使うとコードがシンプルになる- UI更新はメインスレッドで行う
通信処理はアプリ開発において非常に重要な要素です。
URLSession
を正しく使えるようになることで、APIとのやり取りや外部サービスとの連携がスムーズに行えるようになります。
まずは基本的なGET/POSTの書き方から試してみて、徐々に非同期処理やエラーハンドリングにも慣れていきましょう。