APIクライアントは、リクエストの情報をもとにWeb APIを呼び出し、そのレスポンスを呼び出し元に返します。
webAPIをアプリで利用するときにはURLSessionを使用しますが、URLRequestクラス、HTTPURLResponseクラスも使用するので、その説明もしています。
URLRequest
URLRequestクラスは通信のリクエストをカプセル化した型です。
HTTPリクエストのURL、HTTPヘッダ、HTTPメソッド、HTTPボディなどの情報を持つことができます。URLRequestクラスのインスタンスは、URLSessionクラスを通じて、最終的に次のようなHTTPリクエストとしてHTTPサーバに送信されます。
HTTPリクエストの例(中身)
GET /search/repositories HTTP/1.1
Host: api.github.com
Accept: application/json
Accept-Encoding: gzip, deflate
Accept-Language: ja-jp
Connection: keep-alive
User-Agent: Demo/1 CFNetwork/760.1.2 Darwin/15.0.0 (x86_64)
HTTPURLResponse
HTTPURLResponse型はHTTPレスポンスのメタデータをカプセル化したクラスで、HTTPステータスコードなどの情報を表します。
例
下記コードにて、受け取ったHTTPレスポンスのメタデータには、dataTask(with:completionHandler:)メソッドのコールバック関数の中でアクセスできます。
コールバック関数の第2引数の型はURLResponse型ですが、このURLResponse型はHTTPURLResponse型のスーパークラスです。
URLResponse型はHTTPレスポンスに限らない、より抽象的なレスポンスを表現するための型です。
import UIKit
//url生成
let url = URL(string: "https://api.github.com/search/repositories?q=swift")!
//httpリクエスト生成
let urlRequest = URLRequest(url: url)
//セッション情報取り出し
let session = URLSession.shared
//レスポンスを受け取る通信処理
let task = session.dataTask(with: urlRequest) {data, urlResponse, error in
//コールバッククロージャの第2引数はURLResponse型なのでHTTPURLResponseにダウンキャスト
if let urlResponse = urlResponse as? HTTPURLResponse {
//----以下“HTTPレスポンスのメタデータ-------
urlResponse.statusCode // 200
// "Tue, 10 Nov 2015 19:23:13 GMT"
urlResponse.allHeaderFields["Date"]
// "application/json; charset=utf-8"
urlResponse.allHeaderFields["Content-Type"]
}
}
task.resume()
URLSession
webAPIをアプリで利用するときにはURLSessionを使用します。
URLSessionクラスは通信タスクを管理するためのクラスです。
HTTPリクエストを表すURLRequest型の情報をもとにHTTPサーバと通信し、その結果はHTTPレスポンスを表すHTTPURLResponse型とバイナリデータを表すData型のペアとして表現されます。
リクエストごとの通信タスクはURLSessionTaskクラスとして表現され、URLSessionクラスはそれぞれのタスクを管理します。
URLSessionTaskクラス
URLSessionTaskクラスには、用途ごとに
- URLSessionDataTask
JSONデータ等のデータの取得を行うには、URLSessionDataTaskクラスを利用します。
サーバから取得したデータ結果をDataとしてメモリ上に保持します。 - URLSessionUploadTask
サーバにデータをアップロードするために使用する - URLSessionDownloadTask
サーバからデータを取得し、ファイルに保存するために使用する
の3つのサブクラスがあります。
仕様
sharedクラスプロパティ
sharedクラスプロパティを利用することでURLSessionクラスのインスタンスを簡単に取得できますが、キャッシュやCookieの設定などを細かく設定したい場合は、URLSessionConfiguration型の値を引数に取るイニシャライザを使用して、URLSessionクラスのインスタンスを生成します。
dataTask(with:completionHandler:)メソッド
URLRequest型のインスタンスからURLSessionDataTask型の値を生成して通信を行うにはdataTask(with:completionHandler:)メソッドを呼び出します。
let session = URLSession.shared
let task = session.dataTask(with: URLRequest, completionHandler: (Data?, URLResponse?, Error?) -> Void)
第1引数にはURLRequest型の値を渡し、第2引数には通信の完了時に実行されるクロージャを渡します。dataTask(with:completionHandler:)メソッドの戻り値はURLSessionDataTask型です。
戻り値のURLSessionDataTaskクラスの値に対してresume()メソッドを実行すると、通信が開始されます。
import UIKit
//URLSessionクラスのインスタンスを取得
let session = URLSession.shared
let task = session.dataTask(with: urlRequest) {
data, urlResponse, error in
// 通信完了時に実行される
}
task.resume()
例
下記はヤフーのトップ画面の情報のリクエスト、レスポンスの簡単なやりとりになります。
import UIKit
import PlaygroundSupport
//非同期処理の実行許可
PlaygroundPage.current.needsIndefiniteExecution = true
//URLSessionのインスタンス取得
let session = URLSession.shared
//urlオブジェクト生成
let url = URL(string: "https://www.yahoo.co.jp")!
//リクエストオブジェクト生成
let request = URLRequest(url: url)
//httpリクエストを元に処理タスクを生成(レスポンスを受け取る通信処理)
let task = session.dataTask(with: request){(data, response, err) in
//▼以下データ取得後の処理(コールバック)
//エラーが返ってきた場合は処理を終(エラーでない時はerrはnil)
if err != nil {
return
}
//リクエストしたサーバ(ヤフー)からデータが返って来なかった場合はエラーを表示して処理を終了
guard let data = data else {
print("エラー!サーバから応答がありません。")
return
}
//サーバから返ってきたデータ(レスポンスデータ(バイナリデータ))を文字列に変換して表示
if let val = String(data: data, encoding: String.Encoding.utf8){
print(val)
}else {
print("文字列に変換できませんでした。")
}
}
//処理開始
task.resume()
定数valの表示結果
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="content-style-type" content="text/css">
<meta http-equiv="content-script-type" content="text/javascript">
<meta name="description" content="日本最大級のポータルサイト。検索、オークション、ニュース、メール、コミュニティ、ショッピング、など80以上のサービスを展開。あなたの生活をより豊かにする「ライフ・エンジン」を目指していきます。">
<meta name="robots" content="noodp">
<meta name="google-site-verification" content="fsLMOiigp5fIpCDMEVodQnQC7jIY1K3UXW5QkQcBmVs">
<link rel="canonical" href="https://www.yahoo.co.jp/" />
<link rel="alternate" media="only screen and (max-width: 640px)" href="https://m.yahoo.co.jp/">
<link rel="alternate" href="android-app://jp.co.yahoo.android.yjtop/yahoojapan/home/top">
<title>Yahoo! JAPAN</title>
・・・・・・・・・・