# HTTPによる通信
Swiftは、Foundationフレームワークを使うことでHTTPによる通信を行うことができます。通常、APIサーバーなどに接続するために Alamofire/Alamofire や AFNetworking/AFNetworking などのライブラリを使うことが一般的ですが、Foundationの URLSession
でもGETやPOSTなどによる通信を実現することができます。
# URLSessionConfiguration
URLSessionConfiguration
は、URLSession
を使用するときの動作とポリシーを定義します。URLSessionConfigurationの設定は常に最初に行う必要があります。データをアップロードまたはダウンロードするとき、この設定を使用して、タイムアウト値、キャッシュ、クッキーの使用や端末回線での接続の許可など、を制御します。
URLSessionConfiguration
の設定は3種類あります。
# default
default
は、キャッシュ、認証情報、クッキーなどを使用するデフォルトの設定オブジェクトを作成します。URLSessionConfiguration.default
で設定を作成します。
# ephemeral
ephemeral
は、default
の設定と似ていますが、セッションに関するデータをディスクに書き込まないでメモリに保存します。プライベートモードで動作し、セッションが破棄されるとキャッシュなどのデータも無くなります。URLSessionConfiguration.ephemeral
で設定を作成します。
# background
background
は、バックグラウンドでコンテンツのアップロードとダウンロードを実行することができます。URLSessionConfiguration.backgroundSessionConfiguration()
メソッドで設定を作成します。
# URLSession
URLSession
クラスは、URLで指定されたエンドポイントからデータをダウンロードしたり、アップロードすることができます。それぞれのリクエストはタスクと呼ばれ、URLSessionはそれをまとめるクラスになります。
# タスク
URLSessionクラスが取り扱うリクエストのタスクは、次のような種類があります。
# URLSessionDataTask
URLSessionDataTask
はリクエストの基本のタスクで、Dataオプジェクトを経由してデータの送受信を行います。iOSアプリだとバックグランドの処理ができないので主に小さいデータのやりとりをする際に使います。
# URLSessionUploadTask
URLSessionUploadTask
はデータのアップロードを行います。URLSessionDataTaskと異なり、バックグランドの処理が可能で、時間を要する通信の際に使います。
# URLSessionDownloadTask
URLSessionDownloadTask
は、サーバーからデータをダウンロードします。URLSessionUploadTask同様に、バックグランドの処理が可能で、ダウンロードしたデータをファイルに保存します。
# GET
GETメソッドを用いた基本的な通信は、DataTaskを使います。
簡単な例として、iTunes Search APIにアクセスして情報を取得してみましょう。
Playgroundで実行するため次の設定をします。
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
次に、URLSessionConfiguration
の設定をします。今回は、default
の設定を使います。
// URLSessionConfiguration の設定をする
let config = URLSessionConfiguration.default
作成した設定を元に URLSession
セッションのインスタンスを生成します。
// URLSession セッションのインスタンスを生成
let session = URLSession(configuration: config)
次に、URLを作ります。
// URLを作成
var urlComponents = URLComponents(string: "https://itunes.apple.com/search")
urlComponents?.query = "media=music&entity=song&term=justin"
let url = urlComponents?.url
最後に、.dataTask
でGET通信をしてデータを取得します。
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
// URLSessionConfiguration の設定をする
let config = URLSessionConfiguration.default
// URLSession セッションのインスタンスを生成
let session = URLSession(configuration: config)
// URLを作成
var urlComponents = URLComponents(string: "https://itunes.apple.com/search")
urlComponents?.query = "media=music&entity=song&term=justin"
let url = urlComponents?.url
// GET通信を実行
let task = session.dataTask(with: url!) { data, response, error in
if let error = error {
print(error.localizedDescription)
return
}
guard let data = data, let response = response as? HTTPURLResponse else {
print("データがありませんでした。")
return
}
if response.statusCode == 200 {
do {
let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments)
print(json)
} catch {
print("不正なデータです")
}
// 処理...
}
}
task.resume()
以下が実行結果です。取得したデータをJSON化させています。
{
resultCount = 50;
results = (
{
artistId = 466532;
artistName = Korn;
...
},
...
)
}
URLSessionConfigurationの設定が default
の場合は、明示的にURLSessionConfiguration.defaultを設定しなくてもURLSessionクラスの shared
を使って同じようにデータを取得することができます。
// URLSession.shared を使う
let task = URLSession.shared.dataTask(with: url!) { data, response, error in
// ...
}
task.resume()
# POST
# DataTask
DataTaskでは、POSTメソッドを使った通信をすることもできます。POST通信をする際には、メソッドの設定やボディの情報を変更するため URLRequest型
を使う必要があります。
次の例では、http://localhost:8080/users
に対してPOST通信をしてUserオブジェクトをJSON形式で送信します。
まずは、URLRequest
でリクエストを生成します。
var url = URL(string: "http://localhost:8080/users")!
// URLを渡してリクエストを作成する
var request = URLRequest(url: url)
次に、POSTメソッドとcontent-typeを設定します。
// POSTメソッドを追加する
request.httpMethod = "POST"
// content-type を application/json に設定する
request.addValue("application/json", forHTTPHeaderField: "content-type")
次に、ボディに送信するためのデータを設定します。request.httpBody
に送信したいデータをJSON形式にエンコードして代入します。
// データをを用意する
struct User: Codable {
let id: String
let name: String
}
let user = User(id: "1", name: "Taro")
do {
// JSON形式にエンコードして、データをhttpBodyにセットする
request.httpBody = try JSONEncoder().encode(user)
} catch {
print("不正なデータです")
}
最後に、データをPOST送信します。
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
var url = URL(string: "http://localhost:8080/users")!
// URLを渡してリクエストを作成する
var request = URLRequest(url: url)
// POSTメソッドを追加する
request.httpMethod = "POST"
// content-type を application/json に設定する
request.addValue("application/json", forHTTPHeaderField: "content-type")
// データをを用意する
struct User: Codable {
let id: String
let name: String
}
let user = User(id: "1", name: "Taro")
do {
// JSON形式にエンコードして、データをhttpBodyにセットする
request.httpBody = try JSONEncoder().encode(user)
} catch {
print("不正なデータです")
}
// データをPOST送信する
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if error != nil {
print("エラー")
return
}
print("成功")
}
task.resume()
# UploadTask
UploadTaskでもPOST通信をすることができます。アップロード可能なデータは、画像やファイルなど多様なデータをアップロードすることができます。
DataTask同様に、URLRequest
でリクエストを生成します。
var url = URL(string: "http://localhost:8080/users")!
// URLを渡してリクエストを作成する
var request = URLRequest(url: url)
次に、POSTメソッドとcontent-typeを設定します。
// POSTメソッドを追加する
request.httpMethod = "POST"
// content-type を application/json に設定する
request.addValue("application/json", forHTTPHeaderField: "content-type")
そして、URLSession.shared.uploadTask()
でデータをアップロードします。
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
var url = URL(string: "http://localhost:8080/users")!
// URLを渡してリクエストを作成する
var request = URLRequest(url: url)
// POSTメソッドを追加する
request.httpMethod = "POST"
// content-type を application/json に設定する
request.addValue("application/json", forHTTPHeaderField: "content-type")
// データをを用意する
struct User: Codable {
let id: String
let name: String
}
let user = User(id: "1", name: "Taro")
var uploadData = try JSONEncoder().encode(user)
// uploadTaskでJSON形式のデータを送信する
let task = URLSession.shared.uploadTask(with: request, from: uploadData) { data, response, error in
if error != nil {
print("エラー")
return
}
print("成功")
}
task.resume()