URLローディングシステムプログラミングガイド

URL
ローディングシステム
プログラミングガイド
目次
URLローディングシステムについて 6
はじめに 7
URL読み込み 8
ヘルパークラス 9
リダイレクトとその他のリクエスト変更の処理 10
認証と証明書 11
キャッシュ管理 12
cookieストレージ 12
プロトコルのサポート 13
この文書の使い方 13
関連項目 14
NSURLSessionの使用 15
URLセッションの概念の理解 15
セッションの種類 16
タスクの種類 16
バックグラウンド転送の考慮事項 16
ライフサイクルとデリゲートのやり取り 18
NSCopyingの挙動 18
デリゲートクラスインターフェイスの例 18
セッションの作成と設定 19
システム提供のデリゲートを使用したリソースのフェッチ 22
カスタムデリゲートを使用したデータのフェッチ 23
ファイルのダウンロード 24
ボディコンテンツのアップロード 27
NSDataオブジェクトを使用したボディコンテンツのアップロード 27
ファイルを使用したボディコンテンツのアップロード 28
ストリームを使用したボディコンテンツのアップロード 28
ダウンロードタスクを使用したファイルのアップロード 29
認証とカスタムTLSチェーン認証の処理 29
iOSでのバックグラウンドアクティビティの処理 30
NSURLConnectionの使用 33
接続の作成 33
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
2
目次
POST要求を行う 37
完了ハンドラブロックを使ってデータを取得する 39
データを同期取得する 40
NSURLDownloadの使用 42
事前設定したダウンロード先へのダウンロード 42
提案されたファイル名を使用したファイルのダウンロード 44
ダウンロードの進行状況の表示 46
ダウンロードの再開 48
エンコードされたファイルのデコード 48
URLデータのエンコード 50
リダイレクトとその他のリクエスト変更の処理 52
チャレンジ認証とTLSチェーン認証 55
チャレンジ認証への対応方法の決定 55
チャレンジ認証への対応 56
証明書の提供 57
証明書なしでの続行 57
接続のキャンセル 58
認証例 58
カスタムTLSチェーン認証の実行 59
Understanding Cache Access 61
Using the Cache for a Request 61
Cache Use Semantics for the HTTP Protocol 62
Controlling Caching Programmatically 62
cookieとカスタムプロトコル 65
cookieストレージ 65
プロトコルのサポート 66
URLセッションのライフサイクル 68
システム提供のデリゲートを使用したURLセッションのライフサイクル 69
カスタムデリゲートを使用したURLセッションのライフサイクル 70
書類の改訂履歴 75
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
3
リスト
NSURLSessionの使用 15
リスト 1-1
リスト 1-2
リスト 1-3
リスト 1-4
リスト 1-5
リスト 1-6
リスト 1-7
リスト 1-8
リスト 1-9
デリゲートクラスインターフェイスの例 18
セッションの作成と設定 20
同じ設定オブジェクトで2番目のセッションを作成 22
システム提供のデリゲートを使用したリソースリクエスト 23
データタスクの例 24
ダウンロードタスクの例 25
ダウンロードタスクを実行するデリゲートメソッド 25
iOSでのバックグラウンドダウンロードのセッションデリゲートメソッド 30
iOSでのバックグラウンドダウンロードアプリケーションデリゲートメソッド 31
NSURLConnectionの使用 33
リスト 2-1
リスト 2-2
リスト 2-3
リスト 2-4
リスト 2-5
リスト 2-6
NSURLConnectionを使用した接続の作成 34
connection:didReceiveResponse:の実装例 35
connection:didReceiveData:の実装例 35
connection:didFailWithError:の実装例 36
connectionDidFinishLoading:の実装例 37
POST要求を行うようNSMutableRequestオブジェクトを設定するコード例 38
NSURLDownloadの使用 42
リスト 3-1
リスト 3-2
リスト 3-3
リスト 3-4
リスト 3-5
ダウンロード先ファイルの場所を事前設定したNSURLDownloadの使用 42
ダウンロードから導出されたファイル名でのNSURLDownloadの使用 44
download:didCreateDestination:を使用した最終的なファイル名のログ記録 46
ダウンロードの進行状況の表示 47
download:shouldDecodeSourceDataOfMIMEType:の実装例 48
リダイレクトとその他のリクエスト変更の処理 52
リスト 5-1
connection:willSendRequest:redirectResponse:の実装例 53
チャレンジ認証とTLSチェーン認証 55
リスト 6-1
connection:didReceiveAuthenticationChallenge:デリゲートメソッドを使用した
例 58
Understanding Cache Access 61
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
4
リスト
リスト 7-1
Example connection:withCacheResponse: implementation 63
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
5
URLローディングシステムについて
このガイドでは、標準的なインターネットプロトコルを使用して、URLと対話し、サーバと通信する
ために使用可能な、Foundationフレームワーククラスについて説明します。これらのクラスは一体と
なって、URLローディングシステム と呼ばれます。
URLローディングシステムは、クラスとプロトコルのセットで、URLによって参照されるコンテンツ
にアプリケーションがアクセスできるようにします。このテクノロジの中心にはNSURLクラスがあ
り、このクラスによってアプリケーションが参照先のULRとリソースを操作できるようになります。
そのクラスをサポートするために、Foundationフレームワークは、ULRのコンテンツのロード、サー
バへのデータのアップロード、cookieストレージの管理、レスポンスキャッシュの制御、アプリケー
ション固有の方法での証明書ストレージと認証の処理、カスタムプロトコル拡張機能の書き込みを可
能にするクラスの充実したコレクションを提供します。
URLローディングシステムは、次のプロトコルを使用してリソースにアクセスするためのサポートを
提供します。
●
File Transfer Protocol(ftp://)
●
Hypertext Transfer Protocol(http://)
●
暗号化付きHypertext Transfer Protocol(https://)
●
ローカルファイルのURL(file:///)
●
データのURL(data://)
ユーザのシステム環境設定を使用して、プロキシサーバとSOCKSゲートウェイの両方も透過的にサ
ポートします。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
6
URLローディングシステムについて
はじめに
Important: URLローディングシステムに加え、OS XやiOSには、Safariなど他のアプリケーションで
URLを開くためのAPIもあります。この資料では、このAPIについては解説しません。
OS XのLaunchサービスについては、『Launch Services Programming Guide 』を参照してください。
また、NSWorkSpaceクラスのopenURL:メソッド(OS X用)については、『NSWorkspace Class
Reference 』に解説があります。
UIApplicationクラスのopenURL:メソッド(iOS用)については、『UIApplicationClassReference 』
を参照してください。
はじめに
URLローディングシステムには、URLをロードするためのクラスに加え、これと連携する重要なヘル
パクラスが多数付属しており、状況に応じて動作を補正できるようになっています。主なヘルパクラ
スは、プロトコル操作、認証と証明書、cookieストレージ、設定管理、キャッシュ管理の5つに分類さ
れます。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
7
URLローディングシステムについて
はじめに
URL読み込み
URLローディングシステムで最も一般的に使用されるクラスにより、アプリケーションはソースから
URLのコンテンツを取得できます。コンテンツを取得するにはアプリケーションの要件に応じて多く
の方法があります。選択するAPIは、アプリケーションが対象とするOS XまたはiOSのバージョン、お
よびデータをファイルとして取得するかデータのメモリ上ブロックとして取得するかによって異なり
ます。
●
●
●
iOS 7以降またはOS X v10.9以降では、NSURLSessionがURLリクエストを実行する新しいコードに
好ましいAPIです。
旧バージョンのOS Xをサポートする必要があるソフトウェアでは、NSURLDownloadを使用して、
URLのコンテンツをディスク上のファイルにダウンロードすることができます。
旧バージョンのiOSまたはOS Xをサポートする必要があるソフトウェアでは、NSURLConnection
を使用して、URLのコンテンツをメモリにダウンロードすることができます。その後、必要に応
じてデータをディスクに書き込むことができます。
使用する具体的なメソッドは、データをメモリにフェッチするかディスクにダウンロードするかに
よって大きく異なります。
データ(メモリ上)としてコンテンツのフェッチ
大まかに言うと、URLデータをフェッチするには次の2つの基本的な方法があります。
●
●
単純なリクエストの場合、コンテンツはNSURLSession APIを使って、NSURLオブジェクトから直
接、NSDataオブジェクトまたはディスク上のファイルとして取得します。
より複雑なリクエスト(たとえば、データをアップロードするリクエストなど)の場合は、
NSURLRequestオブジェクト(またはその可変サブクラス、NSMutableURLRequest)を
NSURLSessionまたはNSURLConnectionに提供します。
どの方法を選択したかに関係なく、アプリケーションは次の2つの方法でレスポンスを取得できます。
●
●
完了ハンドラブロックを提供します。URL読み込みクラスは、サーバからのデータの取得を終了
すると、完了ハンドラブロックを呼び出します。
カスタムデリゲートを提供します。ULR読み込みクラスは、送信元からデータを受信すると、定
期的にデリゲートメソッドを呼び出します。アプリケーションは、必要に応じて、そのデータを
集計する役割を果たします。
データ自体に加えて、URLローディングクラスは、MIMEタイプやコンテンツ長などのリクエストに関
連付けられたメタデータをカプセル化するレスポンスオブジェクトを、デリゲートまたは完了ハンド
ラブロックに提供します。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
8
URLローディングシステムについて
はじめに
関連する章: “NSURLSessionの使用” (15 ページ)、“NSURLConnectionの使用” (33 ページ)
ファイルとしてのコンテンツのダウンロード
大まかに言うと、URLのコンテンツをファイルにダウンロードするには次の2つの基本的な方法があり
ます。
●
●
単純なリクエストの場合、コンテンツはNSURLSession APIを使って、NSURLオブジェクトから直
接、NSDataオブジェクトまたはディスク上のファイルとして取得します。
より複雑なリクエスト(たとえば、データをアップロードするリクエストなど)の場合は、
NSURLRequestオブジェクト(またはその可変サブクラス、NSMutableURLRequest)を
NSURLSessionまたはNSURLDownloadに提供します。
NSURLSessionクラスは、NSURLDownloadクラスと比較して2つの大きな利点を提供します。それは、
iOSで利用できることと、アプリケーションが一時停止、終了、またはクラッシュしたときにバック
グラウンドでダウンロードを続行できることです。
注意: NSURLDownloadまたはNSURLSessionインスタンスによって開始されたダウンロード
は、キャッシュされません。結果をキャッシュする必要がある場合、アプリケーションは
NSURLConnectionまたはNSURLSessionのいずれかを使用し、データをディスク自体に書き
込む必要があります。
関連する章: “NSURLSessionの使用” (15 ページ)、“NSURLDownloadの使用” (42 ページ)
ヘルパークラス
URL読み込みクラスでは、追加メタデータを提供する2つのヘルパークラスが使用されます。1つはリ
クエスト自体のためのものでNSURLRequest、もう1つはサーバーのレスポンスのためのものです
(NSURLResponse)。
URLリクエスト
NSURLRequestオブジェクトは、URLおよび任意のプロトコル固有のプロパティをプロトコルに依存し
ない方法でカプセル化します。また、ローカルにキャッシュされたどのデータを使用するかに関係な
く、ポリシーを指定し、NSURLConnectionまたはNSURLDownloadで使用されたときに、接続タイム
アウトを設定するインターフェイスを提供します。(NSURLSessionでは、タイムアウトはセッショ
ン前を基準として設定されます。)
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
9
URLローディングシステムについて
はじめに
注意: クライアントアプリケーションがNSMutableURLRequestのインスタンスを使用して
接続またはダウンロードを開始すると、リクエストからディープコピーが作成されます。ダ
ウンロードが始まると、開始リクエストに対する変更は反映されません。
一部のプロトコルでは、プロトコル固有のプロパティがサポートされます。たとえば、HTTPプロトコ
ルはHTTPリクエストボディ、ヘッダ、および転送メソッドを返すNSURLRequestにメソッドを追加し
ます。また、NSMutableURLRequestにメソッドを追加して、それらの値を設定します。
URLリクエストオブジェクトの使用の詳細については、本書全体にわたって説明します。
レスポンスメタデータ
リクエストに対するサーバからのレスポンスは、コンテンツについて記述するメタデータとコンテン
ツデータ自体の2つの部分として表示できます。ほとんどのプロトコルに共通するメタデータは
NSURLResponseクラスによってカプセル化され、MIMEタイプ、想定されるコンテンツ長、テキスト
エンコード(該当する場合)、およびレスポンスを提供したULRから構成されます。NSURLResponse
のプロトコル固有のサブクラスは、追加のメタデータを提供できます。たとえば、NSHTTPURLResponse
は、Webサーバによって返されるヘッダとステータスコードを格納します。
Important: NSURLResponseオブジェクトに格納されるのは、レスポンスのメタデータのみです。
さまざまなURL読み込みクラスが、完了ハンドラブロックを介して、またはオブジェクトのデリ
ゲートに対して、レスポンスデータ自体をアプリケーションに提供します。
NSCachedURLResponseインスタンスは、NSURLResponseオブジェクト、URLコンテンツデータ、
およびアプリケーションによって提供される任意の追加情報をカプセル化します。詳細について
は、“キャッシュ管理” (12 ページ)を参照します。
URLレスポンスオブジェクトの使用の詳細については、本書全体にわたって説明します。
リダイレクトとその他のリクエスト変更の処理
HTTPなどの一部のプロトコルは、コンテンツが別のURLに移動したことをサーバがアプリケーション
に通知する方法を提供します。URL読み込みクラスは、これが発生したときにデリゲートに通知でき
ます。アプリケーションが適切なデリゲートメソッドを提供すると、アプリケーションは、リダイレ
クトに従うか、リダイレクトからレスポンスボディを返すか、エラーを返すかを決定できます。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
10
URLローディングシステムについて
はじめに
関連する章: “リダイレクトとその他のリクエスト変更の処理” (52 ページ)
認証と証明書
一部のサーバは特定のコンテンツへのアクセスを制限し、アクセスするためにある種の証明書(クラ
イアント証明書、ユーザ名とパスワードなど)を提供することによる認証をユーザにリクエストしま
す。Webサーバの場合は、制限されたコンテンツが1つの証明書セットを必要とする領域にグループ
化されます。アプリケーションがサーバを信用すべきかどうかを評価するための逆方向の信用の決定
に、証明書(具体的には証明書)も使用されます。
URL読み取りシステムは、証明書と保護された領域をモデル化するクラスを提供するほか、安全な証
明書の永続性を提供します。アプリケーションは、単一のリクエストの間、アプリケーションが起動
している期間、またはユーザのキーチェーンで、証明書が永続的に持続するように指定できます。
注意: 永続ストレージに格納された証明書は、ユーザのキーチェーンに保持され、すべての
アプリケーション間で共有されます。
NSURLCredentialクラスは、認証情報(たとえば、ユーザ名とパスワードなど)と、永続的な挙動か
ら構成される証明書をカプセル化します。NSURLProtectionSpaceクラスは、特定の証明書を必要と
する領域を表します。予約領域は、1つのURLに制限でき、Webサーバ上の領域をカプセル化し、プロ
キシを参照します。
NSURLCredentialStorageクラスの共有インスタンスは、証明書ストレージを管理し、
NSURLCredentialオブジェクトの、認証を行う対応するNSURLProtectionSpaceオブジェクトへの
マッピングを行います。
NSURLAuthenticationChallengeクラスは、リクエストを認証するためにNSURLProtocol実装が必
要とする情報(提示された証明書、関係する予約領域、認証が必要であることを判定するためにプロ
トコルが使用したエラーまたはレスポンス、および認証試行の数)をカプセル化します。
NSURLAuthenticationChallengeインスタンスは、認証を開始したオブジェクトも明示します。sender
と呼ばれる開始オブジェクトは、NSURLAuthenticationChallengeSenderプロコトルに従わなけれ
ばなりません。
NSURLAuthenticationChallengeインスタンスは、URLローディングシステムに認証が必要であるこ
とを通知するために、NSURLProtocolサブクラスによって使用されます。このインスタンスは、カス
タマイズされた認証処理を容易にするNSURLConnectionおよびNSURLDownloadのデリゲートメソッ
ドにも提供されます。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
11
URLローディングシステムについて
はじめに
関連する章: “チャレンジ認証とTLSチェーン認証” (55 ページ)
キャッシュ管理
URLローディングシステムは、アプリケーションがネットワーク接続への依存を減らし、それまでに
キャッシュしたレスポンスの処理を高速化できるようにする、ディスク上とメモリ上の複合キャッ
シュを提供します。キャッシュはアプリケーション単位で格納されます。キャッシュは、NSURLRequest
オブジェクトを開始することによって、指定されたキャッシュポリシーに従って、NSURLConnection
によって照会されます。
NSURLCacheクラスは、キャッシュサイズとディスク上のその場所を設定するメソッドを提供します。
キャッシュレスポンスを含むNSCachedURLResponseオブジェクトのコレクションを管理するメソッ
ドも提供します。
NSCachedURLResponseオブジェクトは、NSURLResponseオブジェクトおよびURLコンテンツデータを
カプセル化します。NSCachedURLResponseは、カスタムデータをキャッシュするためにアプリケー
ションが使用できる、ユーザ情報辞書も提供します。
すべてのプロトコル実装がレスポンスキャッシュをサポートするわけではありません。現在は、http
およびhttpsリクエストのみがキャッシュされます。
NSURLConnectionオブジェクトは、connection:willCacheResponse:デリゲートメソッドを実装す
ることによって、レスポンスをキャッシュするかどうかや、レスポンスをメモリ上にのみキャッシュ
すべきかどうかを制御します。
関連する章: “Understanding Cache Access” (61 ページ)
cookieストレージ
HTTPプロトコルの処理状態を把握しない性質により、クライアントは多くの場合、cookieを使って、
データアクセスURLリクエストの永続ストレージを提供します。URLローディングシステムは、cookie
の作成や管理のほか、HTTPリクエストの一部としてcookieを送信し、あるいはWebサーバのレスポン
スを分析してcookieを受信するためのインターフェイスを備えています。
OS XおよびiOSは、NSHTTPCookieStorageクラスを提供します。このクラスは、NSHTTPCookieオブ
ジェクトのコレクションを管理するためのインターフェイスを提供します。OS Xでは、cookieストレー
ジはアプリケーション(iOS)全体で共有され、cookieストレージはアプリケーション単位です。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
12
URLローディングシステムについて
この文書の使い方
関連する章: “cookieストレージ” (65 ページ)
プロトコルのサポート
URLローディングシステムでは、http、https、file、ftp、およびdataプロトコルがネイティブに
サポートされています。ただし、URLローディングシステムでは、アプリケーションが独自のクラス
を登録して、追加のアプリケーションレイヤネットワークプロトコルをサポートすることもできま
す。プロトコル固有のプロパティをURLリクエストおよびURLレスポンスオブジェクトに追加するこ
ともできます。
関連する章: “cookieとカスタムプロトコル” (65 ページ)
この文書の使い方
本書は各章で説明するURL読み込みクラスに基づいて大きく分けられています。使用するAPIを決定す
るには、“URL読み込み” (8 ページ)をお読みください。使用するAPIの決定後、該当するアプリケー
ション固有の章をお読みください。
●
NSURLSessionクラスを使って、非同期にURLのコンテンツをメモリにフェッチし、あるいはファ
イルをディスクにダウンロードする手順については、“NSURLSessionの使用” (15 ページ)で解説
します。次いで“URLセッションのライフサイクル” (68 ページ)で、NSURLSessionがそのデリ
ゲートと対話する仕組みについて詳細に説明します。
●
NSURLConnectionクラスを使って、非同期にURLのコンテンツをメモリにフェッチする手順につ
いては、“NSURLConnectionの使用” (33 ページ)を参照してください。
●
NSURLDownloadクラスを使って、非同期にファイルをディスクにダウンロードする手順について
は、“NSURLDownloadの使用” (42 ページ)を参照してください。
API別にまとめたいずれかの章を読んだ後、3つのAPIすべてに関係する次の章もお読みください。
●
●
●
●
“URLデータのエンコード” (50 ページ)では、URLに埋め込んで安全に使えるよう、任意の文字
列をエンコードする方法を説明します。
“リダイレクトとその他のリクエスト変更の処理” (52 ページ)では、URLリクエストの変更に対
応するためのオプションについて説明します。
“チャレンジ認証とTLSチェーン認証” (55 ページ)では、セキュアサーバに対して接続を認証す
るためのプロセスについて説明します。
“Understanding Cache Access” (61 ページ)では、リクエスト中に接続がキャッシュを使用する方
法について説明します。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
13
URLローディングシステムについて
関連項目
●
“cookieとカスタムプロトコル” (65 ページ)では、cookieストレージを管理し、カスタムアプリ
ケーションレイヤプロトコルをサポートするために利用可能なクラスについて説明します。
関連項目
以下のサンプルコードを用意しています。
●
●
●
LinkedImageFetcher (OS X)およびAdvancedURLConnections (iOS)は、カスタム認証で
NSURLConnectionを使用します。
SpecialPictureProtocol (OS X)およびCustomHTTPProtocol (iOS)は、カスタムNSURLProtocolサブ
クラスの実装方法を示します。
QuickLookDownloader (Mac Developer Library)は、NSURLDownloadを使用してインターネットか
らのファイルダウンロードを管理します。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
14
NSURLSessionの使用
NSURLSessionクラスおよび関連クラスは、HTTPを介してコンテンツをダウンロードするAPIを提供し
ます。このAPIは、認証をサポートするデリゲートメソッドの充実したセットを提供し、アプリケー
ションが、動作していなかったりiOSで一時停止されているときに、バックグラウンドでのダウンロー
ドを実行できるようにします。
NSURLSessionAPIを使用するには、アプリケーションが一連のセッションを作成し、そのそれぞれが
関連するデータ転送タスクのグループと協調します。たとえば、Webブラウザを書き込んでいる場合
に、アプリケーションがタブまたはウィンドウごとに1つのセッションを作成する場合があります。
各セッション内で、アプリケーションは一連のタスクを追加し、そのそれぞれが特定のURL(および
元のURLがHTTPリダイレクトを返した場合は後続のURL)のリクエストを表します。
ほとんどのネットワークAPIと同様に、NSURLSession APIは非同期性が高くなります。デフォルトの
システム提供のデリゲートを使用する場合は、転送が成功した場合または転送中にエラーが発生した
ときにアプリケーションにデータを返す完了ハンドラブロックを提供する必要があります。一方、独
自のカスタムデリゲートオブジェクトを提供する場合は、サーバからデータを受信すると(ファイル
ダウンロードの場合は、転送が完了すると)、タスクオブジェクトはそのデータを使用してそれらの
デリゲートのメソッドを呼び出します。
注意: 完了コールバックは主として、カスタムデリゲートの代替手段としての使い方を意図
しています。完了コールバックを引数とするメソッドを用いるタスクの場合、レスポンスや
データ配送を行うデリゲートメソッドが呼び出されることはありません。
NSURLSessionAPIは、この情報をデリゲートに提供するのに加えて、状態および進行状況プロパティ
を提供します。タスクのキャンセル、再起動(再開)、および一時停止をサポートし、一時停止、
キャンセル、または失敗したダウンロードを、それらが中止された場合に、再開する機能を提供しま
す。
URLセッションの概念の理解
セッションのタスクの挙動は、セッションの種類(セッションの作成に使用される設定オブジェクト
の種類によって決まる)、タスクの種類、およびタスクの作成時にアプリケーションがフォアグラウ
ンドにあったかどうか、の3つに依存します。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
15
NSURLSessionの使用
URLセッションの概念の理解
セッションの種類
NSURLSession APIは、3種類のセッションをサポートします。これは、セッションの作成に使用され
る設定オブジェクトの種類によって決まります。
●
●
●
デフォルトセッション は、URLをダウンロードするための、他のFoundationメソッドと同様に動
作します。このセッションは、永続的なディスクベースのキャッシュを使用し、証明書をユーザ
のキーチェーンに格納します。
一時セッション は、データをディスクに格納せず、すべてのキャッシュ、証明書ストアなどは
RAMに保持され、セッションに関連付けられます。したがって、アプリケーションがセッション
を無効にすると、セッションは自動的にパージされます。
バックグラウンドセッション は、別のプロセスがすべてのデータ転送を処理する点を除き、デ
フォルトセッションに似ています。バックグランドセッションには、“バックグラウンド転送の考
慮事項” (16 ページ)で説明するいくつかの追加の制限があります。
タスクの種類
セッション内で、NSURLSessionクラスは、データタスク、ダウンロードタスク、およびアップロー
ドタスクの3種類のタスクをサポートします。
●
●
●
データタスク は、NSDataオブジェクトを使用してデータを送受信します。データタスクは、多
くの場合はインタラクティブな、アプリケーションからサーバへの短いリクエストを対象として
います。データタスクは、データの各部分が受信された後に一度に一部分ずつ、または完了ハン
ドラによって一括して、アプリケーションにデータを返すことができます。データタスクはデー
タをファイルに格納しないため、バックグラウンドセッションではサポートされません。
ダウンロードタスク は、ファイルの形でデータを受信し、アプリケーションが動作していないと
きのバックグラウンドでのダウンロードをサポートします。
アップロードタスクは は、(通常はファイルの形で)データを送信し、アプリケーションが動作
していないときのバックグラウンドでのアップロードをサポートします。
バックグラウンド転送の考慮事項
NSURLSessionクラスは、アプリケーションの一時停止中のバックグラウンド転送をサポートします。
バックグラウンド転送は、バックグラウンドセッションの設定オブジェクト
(backgroundSessionConfiguration:への呼び出しによって返される)を使用して作成されたセッ
ションによってのみ、提供されます。
バックグラウンドセッションでは、実際の転送が別のプロセスによって実行されるため、およびアプ
リケーションのプロセスの再開に比較的コストがかかかるため、いくつかの機能は使用できず、次の
制限が生じます。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
16
NSURLSessionの使用
URLセッションの概念の理解
●
●
●
●
●
セッションはイベント配布のデリゲートを提供する必要があります 。(アップロードやダウン
ロードに対して、デリゲートは進行中の転送に対してと同様に動作します。)
HTTPおよびHTTPSプロトコルのみがサポートされます(カスタムプロトコルはサポートされませ
ん)。
アップロードおよびダウンロードタスクのみがサポートされます(データタスクはサポートされ
ません)。
リダイレクトには常に従います。
アプリケーションがバックグラウンドにあるときにバックグラウンド転送が初期化された場合、
設定オブジェクトのdiscretionaryプロパティはtrueとして扱われます。
再起動されたときのアプリケーションが挙動は、iOSとOS Xで若干異なります。
iOSでは、バックグラウンド転送が証明書を完全なものにした場合や、証明書を必要とする場合に、
アプリケーションが実行されなくなると、iOSはアプリケーションをバックグラウンドで自動的に再
起動し、アプリケーションのUIApplicationDelegateオブジェクトで
application:handleEventsForBackgroundURLSession:completionHandler:メソッドを呼び出し
ます。この呼び出しは、アプリケーションを起動させるセッションの識別子を提供します。アプリ
ケーションは、その完了ハンドラを格納し、同じ識別子でバックグラウンドの設定オブジェクトを作
成し、その設定オブジェクトでセッションを作成します。新しいセッションは、進行中のバックグラ
ウンドアクティビティに自動的に関連付け直されます。後で、セッションが最後のバックグラウンド
ダウンロードタスクを終了すると、セッションデリゲートに
URLSessionDidFinishEventsForBackgroundURLSession:メッセージを送信します。その後、セッ
ションデリゲートは、格納された完了ハンドラを呼び出す必要があります。
iOSでもOS Xでも、ユーザがアプリケーションを再起動すると、アプリケーションは、アプリケーショ
ンが最後に実行されたときに未処理のタスクがあったセッションと同じ識別子でバックグラウンド設
定オブジェクトをすぐに作成し、それらの設定オブジェクトのそれぞれに対してセッションを作成し
ます。これらの新しいセッションも同様に、進行中のバックグラウンドアクティビティに自動的に関
連付け直されます。
注意: (設定オブジェクトの作成時に指定される)識別子ごとに1セッションだけ 作成する
必要があります。同じ識別子を共有する複数のセッションの挙動は定義されていません。
アプリケーションが一時停止している間にタスクが完了すると、デリゲートの
URLSession:downloadTask:didFinishDownloadingToURL:メソッドは、そのタスクとそれに関連
付けられている新たにダウンロードされたファイルのULRによって呼び出されます。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
17
NSURLSessionの使用
デリゲートクラスインターフェイスの例
同様に、タスクに証明書が必要な場合、NSURLSessionオブジェクトは必要に応じてデリゲートの
URLSession:task:didReceiveChallenge:completionHandler:メソッドまたは
URLSession:didReceiveChallenge:completionHandler:メソッドを呼び出します。
バックグラウンド転送でのNSURLSessionの使用例については、Simple Background Transfer を参照して
ください。
ライフサイクルとデリゲートのやり取り
NSURLSessionクラスで行うことに応じて、セッションがそのデリゲートとどのようにやり取りする
のか、デリゲート呼び出しが行われる順序、サーバがリダイレクトを返すとどうなるか、アプリケー
ションが失敗したダウンロードを再開するとどうなるかなど、セッションのライフサイクルを充分に
理解しておくと有用な場合があります。
URLセッションのライフサイクルの詳細については、“URLセッションのライフサイクル” (68 ページ)
をお読みください。
NSCopyingの挙動
セッションオブジェクトやタスクオブジェクトは次のように、NSCopyingプロトコルを実装していま
す。
●
●
アプリケーションがセッションまたはタスクオブジェクトをコピーすると、同じオブジェクトを
取得します。
アプリケーションが設定オブジェクトをコピーすると、無関係に修正可能な新しいコピーを取得
します。
デリゲートクラスインターフェイスの例
以降のタスクについての節のコードスニペットは、リスト 1-1に示すクラスインターフェイスに基づ
いています。
リスト 1-1
デリゲートクラスインターフェイスの例
#import <Foundation/Foundation.h>
typedef void (^CompletionHandlerType)();
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
18
NSURLSessionの使用
セッションの作成と設定
@interface MySessionDelegate : NSObject <NSURLSessionDelegate,
NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>
@property NSURLSession *backgroundSession;
@property NSURLSession *defaultSession;
@property NSURLSession *ephemeralSession;
#if TARGET_OS_IPHONE
@property NSMutableDictionary *completionHandlerDictionary;
#endif
- (void) addCompletionHandler: (CompletionHandlerType) handler forSession: (NSString
*)identifier;
- (void) callCompletionHandlerForSession: (NSString *)identifier;
@end
セッションの作成と設定
NSURLSession APIは、次のような幅広い設定オプションを提供します。
●
●
●
●
●
単一のセッションに固有の方法での、キャッシュ、cookie、証明書、およびプロトコルの非公開
ストレージサポート
特定のリクエスト(タスク)またはリクエストのグループ(セッション)に関連付けられた認証
URLによるファイルアップロードおよびダウンロード。メタデータ(URLおよび設定)からのデー
タ(ファイルのコンテンツ)の分離を促す
ホストごとの最大接続数の設定
一定の時間内にリソース全体をダウンロードできない場合にトリガされる、リソースごとのタイ
ムアウト
●
サポートされるTLSの最大/最小バーション
●
カスタムプロキシ辞書
●
cookieポリシーの制御
●
HTTPパイプラインの挙動の制御
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
19
NSURLSessionの使用
セッションの作成と設定
ほとんどの設定は独立した設定オブジェクトに含まれるため、一般的に使用される設定を再利用でき
ます。セッションオブジェクトをインスタンス化するときは、次を指定します。
●
●
そのセッションの挙動を管理する設定オブジェクトとその中のタスク
必要に応じて、受信したデータを処理し、セッションに固有のその他のイベントやその中のタス
ク(サーバ認証など)を処理し、リソースの読み込みリクエストをダウンロードに変換すべきか
どうかなどを判定するするデリゲートオブジェクト
デリゲートを提供しなかった場合、NSURLSessionオブジェクトではシステム提供のデリゲート
が使用されます。NSURLSessionをこのように使用すると、NSURLSessionで
sendAsynchronousRequest:queue:completionHandler:コンビニエンスメソッドを使用する既
存のコードの代わりに簡単に使用できるようになります。
注意: アプリケーションは、バックグラウンド転送を実行する必要がある場合、カスタ
ムデリゲートを提供する必要があります。
セッションオブジェクトを初期化した後、新しいセッションを作成せずに設定やデリゲートを変更す
ることはできません。
リスト 1-2に、通常、一時、およびバックグラウンドセッションの作成方法の例を示します。
リスト 1-2
セッションの作成と設定
#if TARGET_OS_IPHONE
self.completionHandlerDictionary = [NSMutableDictionary
dictionaryWithCapacity:0];
#endif
/* いくつかの設定オブジェクトを作成する。*/
NSURLSessionConfiguration *backgroundConfigObject = [NSURLSessionConfiguration
backgroundSessionConfiguration: @"myBackgroundSessionIdentifier"];
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration
defaultSessionConfiguration];
NSURLSessionConfiguration *ephemeralConfigObject = [NSURLSessionConfiguration
ephemeralSessionConfiguration];
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
20
NSURLSessionの使用
セッションの作成と設定
/*デフォルトセッションのキャッシュ挙動を設定する。
iOSではキャッシュパスが~/Library/Cachesを基準とした
相対パスである必要があるが、OS Xでは
絶対パスであることが想定される。
*/
#if TARGET_OS_IPHONE
NSString *cachePath = @"/MyCacheDirectory";
NSArray *myPathList = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask, YES);
NSString *myPath
= [myPathList
objectAtIndex:0];
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
NSString *fullCachePath = [[myPath
stringByAppendingPathComponent:bundleIdentifier]
stringByAppendingPathComponent:cachePath];
NSLog(@"Cache path: %@\n", fullCachePath);
#else
NSString *cachePath = [NSTemporaryDirectory()
stringByAppendingPathComponent:@"/nsurlsessiondemo.cache"];
NSLog(@"Cache path: %@\n", cachePath);
#endif
NSURLCache *myCache = [[NSURLCache alloc] initWithMemoryCapacity: 16384
diskCapacity: 268435456 diskPath: cachePath];
defaultConfigObject.URLCache = myCache;
defaultConfigObject.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;
/* 設定ごとにセッションを作成する。*/
self.defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject
delegate: self delegateQueue: [NSOperationQueue mainQueue]];
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
21
NSURLSessionの使用
システム提供のデリゲートを使用したリソースのフェッチ
self.backgroundSession = [NSURLSession sessionWithConfiguration:
backgroundConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];
self.ephemeralSession = [NSURLSession sessionWithConfiguration:
ephemeralConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];
バックグラウンド設定の例外として、セッションの設定オブジェクトを再利用して追加のセッション
を作成することができます。(バックグラウンドセッションの設定は再利用できません。同じ識別子
を共有する2つのバックグラウンドセッションオブジェクトの挙動が定義されていないからです。)
また、設定オブジェクトはいつでも安全に修正できます。セッションを作成すると、作成したセッ
ションは設定オブジェクトのディープコピを実行するため、修正は新しいセッションにのみ影響し、
既存のセッションには影響しません。たとえば、リスト 1-3に示すように、Wi-Fi接続を行っている場
合にのみ取得する必要があるコンテンツの2番目のセッションを作成することができます。
リスト 1-3
同じ設定オブジェクトで2番目のセッションを作成
ephemeralConfigObject.allowsCellularAccess = YES;
// ...
NSURLSession *ephemeralSessionWiFiOnly = [NSURLSession sessionWithConfiguration:
ephemeralConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];
システム提供のデリゲートを使用したリソースのフェッチ
NSURLSessionを使用する最も直接的な方法は、NSURLSessionでの
sendAsynchronousRequest:queue:completionHandler:メソッドの当座の代替としての使用です。
この方針の場合、アプリケーションに組み込む必要があるのは、次の2つのコードのみです。
●
設定オブジェクトを作成するコードと、そのオブジェクトに基づくセッション
●
データが完全に受信された後、そのデータを使って何かを実行する完了ハンドラルーチン
システム提供のデリゲートを使用して、1つのリクエストにつき1行のみのコードを使用して特定の
URLをフェッチすることができます。リスト 1-4 (23 ページ)に、この単純化した形式の例を示しま
す。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
22
NSURLSessionの使用
カスタムデリゲートを使用したデータのフェッチ
注意: システム提供のデリゲートは、ネットワークの挙動の限定的なカスタマイズのみを提
供します。アプリケーションが、カスタム認証やバックグラウンドでのダウンロードなど、
基本的なURLフェッチを超える特殊なニーズある場合、この方法は適していません。完全な
デリゲートを実装する必要がある状況の詳細については、“URLセッションのライフサイク
ル”を参照してください。
リスト 1-4
システム提供のデリゲートを使用したリソースリクエスト
NSURLSession *delegateFreeSession = [NSURLSession sessionWithConfiguration:
defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];
[[delegateFreeSession dataTaskWithURL: [NSURL URLWithString:
@"http://www.example.com/"]
completionHandler:^(NSData *data, NSURLResponse *response,
NSError *error) {
NSLog(@"Got response %@ with error %@.\n", response,
error);
NSLog(@"DATA:\n%@\nEND DATA\n",
[[NSString alloc] initWithData: data
encoding: NSUTF8StringEncoding]);
}] resume];
カスタムデリゲートを使用したデータのフェッチ
カスタムデリゲートを使用してデータを取得する場合、デリゲートは少なくとも次のメソッドを実装
する必要があります。
●
URLSession:dataTask:didReceiveData: リクエストからタスクに、一度に一部分ずつデータを
提供する。
●
URLSession:task:didCompleteWithError: データが完全に受信されたタスクを示す。
URLSession:dataTask:didReceiveData:メソッドが返された後でアプリションがデータを使用する
必要がある場合は、コードが何らかの方法でそのデータを格納する役割を果たします。
たとえば、Webブラウザは、それまでに受信したデータとともにデータが届いたとき、そのデータを
レンダリングすることが必要な場合があります。これを行うには、結果を格納するためにタスクオブ
ジェクトをNSMutableDataオブジェクトにマッピングする辞書を使用し、そのオブジェクトで
appendData:メソッドを使用して、新たに受信したデータを最後に追加します。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
23
NSURLSessionの使用
ファイルのダウンロード
リスト 1-5では、データタスクを作成し、開始する方法を示します。
リスト 1-5
データタスクの例
NSURL *url = [NSURL URLWithString: @"http://www.example.com/"];
NSURLSessionDataTask *dataTask = [self.defaultSession dataTaskWithURL: url];
[dataTask resume];
ファイルのダウンロード
大まかに言うと、ファイルのダウンロードはデータの取得に似ています。アプリケーションは次のデ
リゲートメソッドを実装する必要があります。
●
URLSession:downloadTask:didFinishDownloadingToURL: ダウンロードされたコンテンツが
格納される一時ファイルのURLをアプリケーションに提供する.
Important: このメソッドが返される前に、読み込むためにファイルを開くか、ファイルを永
続的な場所に移動する必要があります。このメソッドが返されると、一時ファイルが元の場所
にまだ存在する場合、その一時ファイルは削除されます。
●
URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
ダウンロードの進行状況に関する状態情報をアプリケーションに提供する。
●
URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes: それまでに失敗した
ダウンロードを再開する試行が成功したことをアプリケーションに通知する。
●
URLSession:task:didCompleteWithError: ダウンロードに失敗したことをアプリケーション
に通知する。
バックグラウンドセッションでダウンロードのスケジューリングを行っている場合は、アプリケー
ションが実行されていないときにダウンロードが続行されます。標準または一時セッションでダウン
ロードのスケジューリングを行っている場合は、アプリケーションが再起動されたときにダウンロー
ドが新たに開始される必要があります。
サーバからの転送中に、ユーザがアプリケーションにダウンロードを一時停止するように指定した場
合、アプリケーションはcancelByProducingResumeData:メソッドを呼び出してタスクをキャンセ
ルすることができます。その後、返されたレジュームデータをdownloadTaskWithResumeData:また
はdownloadTaskWithResumeData:completionHandler:メソッドのいずれかに渡して、ダウンロー
ドを続行する新しいダウンロードタスクを作成することができます。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
24
NSURLSessionの使用
ファイルのダウンロード
転送に失敗すると、デリゲートのURLSession:task:didCompleteWithError:メソッドがNSErrorオ
ブジェクトによって呼び出されます。タスクが再開可能である場合、そのオブジェクトのuserInfo
辞書にはNSURLSessionDownloadTaskResumeDataキーの値が含まれます。アプリケーションは到達
可能性APIを使用して再試行するタイミングを決定する必要があり、その後、
downloadTaskWithResumeData:またはdownloadTaskWithResumeData:completionHandler:を呼
び出して新しいダウンロードタスクを作成してそのダウンロードを続行する必要があります。
リスト 1-6では、適度に大きなファイルをダウンロードする例を示しています。リスト 1-7に、ダウン
ロードタスクを実行するデリゲートメソッドの例を示します。
リスト 1-6
ダウンロードタスクの例
NSURL *url = [NSURL URLWithString:
@"https://developer.apple.com/library/ios/documentation/Cocoa/Reference/"
"Foundation/ObjC_classic/FoundationObjC.pdf"];
NSURLSessionDownloadTask *downloadTask = [self.backgroundSession
downloadTaskWithURL: url];
[downloadTask resume];
リスト 1-7
ダウンロードタスクを実行するデリゲートメソッド
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask
*)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSLog(@"Session %@ download task %@ finished downloading to URL %@\n",
session, downloadTask, location);
#if 0
/* 対処方法 */
[self callCompletionHandlerForSession:session.configuration.identifier];
#endif
#define READ_THE_FILE 0
#if READ_THE_FILE
/* 新たにダウンロードされたファイルを読み込むために開く。*/
NSError *err = nil;
NSFileHandle *fh = [NSFileHandle fileHandleForReadingFromURL:location
error: &err];
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
25
NSURLSessionの使用
ファイルのダウンロード
/* このファイル処理をどこかに格納し、そこからデータを読み込む。*/
// ...
#else
NSError *err = nil;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *cacheDir = [[NSHomeDirectory()
stringByAppendingPathComponent:@"Library"]
stringByAppendingPathComponent:@"Caches"];
NSURL *cacheDirURL = [NSURL fileURLWithPath:cacheDir];
if ([fileManager moveItemAtURL:location
toURL:cacheDirURL
error: &err]) {
/* 参照を新しいURLに格納する*/
} else {
/* エラーを処理する。*/
}
#endif
}
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask
*)downloadTask didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
NSLog(@"Session %@ download task %@ wrote an additional %lld bytes (total %lld
bytes) out of an expected %lld bytes.\n",
session, downloadTask, bytesWritten, totalBytesWritten,
totalBytesExpectedToWrite);
}
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask
*)downloadTask didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
26
NSURLSessionの使用
ボディコンテンツのアップロード
{
NSLog(@"Session %@ download task %@ resumed at offset %lld bytes out of an
expected %lld bytes.\n",
session, downloadTask, fileOffset, expectedTotalBytes);
}
ボディコンテンツのアップロード
アプリケーションは、HTTP POSTリクエストのリクエストボディコンテンツを、NSDataオブジェクト
として、ファイルとして、またはストリームとしての3種類の方法で提供できます。一般に、アプリ
ケーションは次を使用する必要があります。
●
●
●
アプリケーションのデータが既にメモリ上にあり、それを破棄する理由がない場合は、NSDataオ
ブジェクトを使用します。
アップロードするコンテンツがディスク上にファイルとして存在する場合や、そのデータに関連
付けられているメモリを解放できるようにそれをディスクに書き込むことがアプリケーションに
とっての利点である場合は、ファイルを使用します。
ネットワークを介してデータを受信するか、リクエストボディをストリームとして提供する既存
のNSURLConnectionコードを変換する場合は、ストリームを使用します。
選択するスタイルに関係なく、アプリケーションがカスタムセッションデリゲートを提供する場合、
そのデリゲートは
URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:デリゲート
メソッドを実装して、アップロードの進行状況の情報を入手する必要があります。
さらに、アプリケーションがストリームを使用してリクエストボディを提供する場合、アプリケー
ションはURLSession:task:needNewBodyStream:メソッドを実装するカスタムセッションデリゲー
ト(詳細については“ストリームを使用したボディコンテンツのアップロード” (28 ページ)で説明)
を提供する必要があります。
NSDataオブジェクトを使用したボディコンテンツのアップロード
NSDataオブジェクトを使用してボディコンテンツをアップロードするために、アプリケーションは
uploadTaskWithRequest:fromData:またはuploadTaskWithRequest:fromData:completionHandler:
メソッドのいずれかを呼び出してアップロードタスクを作成し、fromDataパラメータを介してリク
エストボディデータを提供します。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
27
NSURLSessionの使用
ボディコンテンツのアップロード
セッションオブジェクトは、データオブジェクトのサイズに基づいて、Content-Lengthヘッダを計
算します。
アプリケーションは、サーバがリクエストする可能性のある追加のヘッダ情報(たとえば、コンテン
ツタイプなど)をURLリクエストオブジェクトの一部として提供する必要があります。
ファイルを使用したボディコンテンツのアップロード
ファイルからボディコンテンツをアップロードするために、アプリケーションは
uploadTaskWithRequest:fromFile:またはuploadTaskWithRequest:fromFile:completionHandler:
メソッドのいずれかを呼び出してアップロードタスクを作成し、タスクがボディコンテンツを読み込
むファイルのURLを提供します。
セッションオブジェクトは、データオブジェクトのサイズに基づいて、Content-Lengthヘッダを計
算します。アプリケーションがContent-Typeヘッダの値を提供しない場合、セッションがその値も
提供します。
アプリケーションは、サーバがリクエストする可能性のある追加のヘッダ情報をURLリクエストオブ
ジェクトの一部として提供することができます。
ストリームを使用したボディコンテンツのアップロード
ストリームを使ってボディコンテンツをアップロードするために、アプリケーションは
uploadTaskWithStreamedRequest:メソッドを呼び出してアップロードタスクを作成します。アプ
リケーションは、タスクがボディコンテンツを読み込む関連付けられたストリームを使用してリクエ
ストオブジェクトを提供します。
アプリケーションは、サーバがリクエストする可能性のある追加のヘッダ情報(たとえば、コンテン
ツタイプやコンテンツ長など)をURLリクエストオブジェクトの一部として提供する必要があります。
さらに、セッションは必ずしも提供されたストリームを巻き戻してデータを読み込み直すことができ
ないため、アプリケーションは、セッションがリクエストを再試行する必要がある場合(たとえば、
認証が失敗した場合など)に新しいストリームを提供する役割を果たします。そのために、アプリ
ケーションはURLSession:task:needNewBodyStream:メソッドを提供します。このメソッドが呼び
出されると、アプリケーションは新しいボディストリームを入手または作成するために必要なアク
ションはどのアクションでも実行し、新しいストリームを使用して、提供された完了ハンドラブロッ
クを呼び出す必要があります。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
28
NSURLSessionの使用
認証とカスタムTLSチェーン認証の処理
注意: ストリームによってボディを提供する場合、アプリケーションは
URLSession:task:needNewBodyStream:デリゲートメソッドを提供する必要があるため、
この方法はシステム提供のデリゲートの使用と互換性がありません。
ダウンロードタスクを使用したファイルのアップロード
ダウンロードタスクのボディコンテンツをアップロードするために、アプリケーションは、NSData
オブジェクトまたはボディストリームを、ダウンロードリクエストの作成時に提供されるNSURLRequest
オブジェクトの一部として提供する必要があります。
ストリームを使用してデータを提供する場合、アプリケーションは、認証が失敗した場合に新しいボ
ディストリームを提供するために、URLSession:task:needNewBodyStream:デリゲートメソッドを
提供する必要があります。このメソッドについては、“ストリームを使用したボディコンテンツのアッ
プロード” (28 ページ)で詳細に説明されています。
ダウンロードタスクは、データがアプリケーションに返される方法を除いて、データタスクと同様に
動作します。
認証とカスタムTLSチェーン認証の処理
リモートサーバが認証が必要であることを示す状態コードを返す場合や、その認証で接続レベルの
チャレンジ(SSLクライアント証明書など)が必要な場合、NSURLSessionはチャレンジ認証デリゲー
トメソッドを呼び出します。
●
●
セッションレベルのチャレンジのNSURLAuthenticationMethodNTLM、
NSURLAuthenticationMethodNegotiate、NSURLAuthenticationMethodClientCertificate、
またはNSURLAuthenticationMethodServerTrustに対して、NSURLSessionオブジェクトはセッ
ションデリゲートのURLSession:didReceiveChallenge:completionHandler:メソッドを呼び
出します。アプリケーションがセッションデリゲートメソッドを提供しない場合、NSURLSession
オブジェクトはタスクデリゲートの
URLSession:task:didReceiveChallenge:completionHandler:メソッドを呼び出してチャレ
ンジを処理します。
セッションレベルのチャレンジ(他のすべて)に対して、NSURLSessionオブジェクトはセッショ
ンデリゲートのURLSession:task:didReceiveChallenge:completionHandler:メソッドを呼
び出してチャレンジを処理します。アプリケーションがセッションデリゲートを提供し、認証を
処理する必要がある場合は、タスクレベルで認証を処理するか、セッションごとにハンドラを明
示的に呼び出すタスクレベルのハンドラを提供します。セッションデリゲートの
URLSession:didReceiveChallenge:completionHandler:メソッドは、非セッションレベルの
チャレンジでは呼び出されません 。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
29
NSURLSessionの使用
iOSでのバックグラウンドアクティビティの処理
注意: Kerberos認証は透過的に処理されます。
ストリームベースのアップロードボディーを持つタスクの認証に失敗した場合、当該タスクが、安全
にストリームを巻き戻し、再利用することはできません。代わりにNSURLSessionオブジェクトは、
デリゲートのURLSession:task:needNewBodyStream:メソッドを呼び出して、新規リクエストに応
じてボディーデータを提供するNSInputStreamオブジェクトを改めて取得します(タスクのアップ
ロードボディーがファイルやNSDataオブジェクトから提供されたものである場合、セッションオブ
ジェクトがこのメソッドを呼び出すことはありません)。
NSURLSessionの認証デリゲートメソッドの書き込みの詳細については“チャレンジ認証とTLSチェー
ン認証” (55 ページ)を参照してください。
iOSでのバックグラウンドアクティビティの処理
iOSでNSURLSessionを使用している場合は、ダウンロードが完了するとアプリケーションが自動的に
再起動されます。アプリケーションの
application:handleEventsForBackgroundURLSession:completionHandler:アプリケーションデ
リゲートメソッドは、適切なセッションを作成し直し、完了ハンドラを格納し、セッションがセッ
ションデリゲートのURLSessionDidFinishEventsForBackgroundURLSession:メソッドを呼び出す
ときにその完了ハンドラを呼び出す役割を果たします。
リスト 1-8およびリスト 1-9に、セッションとアプリケーションの、デリゲートメソッドの例をそれぞ
れ示します。
リスト 1-8
iOSでのバックグラウンドダウンロードのセッションデリゲートメソッド
#if TARGET_OS_IPHONE
-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
{
NSLog(@"Background URL session %@ finished events.\n", session);
if (session.configuration.identifier)
[self callCompletionHandlerForSession: session.configuration.identifier];
}
- (void) addCompletionHandler: (CompletionHandlerType) handler forSession: (NSString
*)identifier
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
30
NSURLSessionの使用
iOSでのバックグラウンドアクティビティの処理
{
if ([ self.completionHandlerDictionary objectForKey: identifier]) {
NSLog(@"Error: Got multiple handlers for a single session identifier.
should not happen.\n");
This
}
[ self.completionHandlerDictionary setObject:handler forKey: identifier];
}
- (void) callCompletionHandlerForSession: (NSString *)identifier
{
CompletionHandlerType handler = [self.completionHandlerDictionary objectForKey:
identifier];
if (handler) {
[self.completionHandlerDictionary removeObjectForKey: identifier];
NSLog(@"Calling completion handler.\n");
handler();
}
}
#endif
リスト 1-9
iOSでのバックグラウンドダウンロードアプリケーションデリゲートメソッド
- (void)application:(UIApplication *)application
handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void
(^)())completionHandler
{
NSURLSessionConfiguration *backgroundConfigObject = [NSURLSessionConfiguration
backgroundSessionConfiguration: identifier];
NSURLSession *backgroundSession = [NSURLSession sessionWithConfiguration:
backgroundConfigObject delegate: self.mySessionDelegate delegateQueue:
[NSOperationQueue mainQueue]];
NSLog(@"Rejoining session %@\n", identifier);
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
31
NSURLSessionの使用
iOSでのバックグラウンドアクティビティの処理
[ self.mySessionDelegate addCompletionHandler: completionHandler forSession:
identifier];
}
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
32
NSURLConnectionの使用
NSURLConnectionは、URLのコンテンツを取得する最も柔軟なメソッドを提供します。このクラス
は、接続を作成したりキャンセルしたりするための簡単なインターフェイスを提供し、接続の多くの
側面のフィードバックと制御を行うデリゲートメソッドのコレクションをサポートします。これらの
クラスは、URL読み込み、キャッシュ管理、認証および証明書、cookieストレージ、およびプロトコ
ルサポートの5つのカテゴリに分類されます。
接続の作成
NSURLConnectionクラスには、URLのコンテンツを取得する、3通りの手段が実装されています。同
期取得、完了ハンドラブロックを用いる非同期取得、独自のデリゲートオブジェクトを用いる非同期
取得です。
URLのコンテンツを同期取得するには:もっぱら バックグラウンドスレッド上で動作するコードか
ら、sendSynchronousRequest:returningResponse:error:を呼び出してHTTPリクエストを実行で
きます。リクエストの処理が完了し、あるいはエラーが発生すると制御が戻ります。詳しくは“デー
タを同期取得する” (40 ページ)を参照してください。
完了ハンドラブロックを使ってURLのコンテンツを取得するには:リクエストの処理状況を監視する
必要がなく、データをすべて受信した後に何らかの処理を施せばよいのであれば、結果を処理するブ
ロックを渡してsendAsynchronousRequest:queue:completionHandler:メソッドを呼び出します。
詳しくは“完了ハンドラブロックを使ってデータを取得する” (39 ページ)を参照してください。
デリゲートオブジェクトを使ってURLのコンテンツを取得するには:少なくとも、
connection:didReceiveResponse:、connection:didReceiveData:、
connection:didFailWithError:、connectionDidFinishLoading:の各デリゲートメソッドを実装
した、デリゲートオブジェクトを用意します。サポートされるデリゲートメソッドは、
NSURLConnectionDelegate、NSURLConnectionDownloadDelegate、および
NSURLConnectionDataDelegateプロトコルに定義されています。
リスト 2-1の例では、URLの接続を開始します。このスニペットはまず、URLを渡し、キャッシュアク
セスポリシー、および接続のタイムアウト間隔を指定して、NSURLRequestインスタンスを生成しま
す。その後、NSURLConnectionインスタンスを作成し、リクエストとデリゲートを指定します。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
33
NSURLConnectionの使用
接続の作成
NSURLConnectionがリクエストの接続を作成できない場合は、initWithRequest:delegate:がnil
を返します。スニペットではさらに、デリゲートに少しずつ渡されるデータを格納するため、
NSMutableDataのインスタンスを作成します。
リスト 2-1
NSURLConnectionを使用した接続の作成
// Create the request.
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL
URLWithString:@"http://www.apple.com/"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// Create the NSMutableData to hold the received data.
// receivedData is an instance variable declared elsewhere.
receivedData = [NSMutableData dataWithCapacity: 0];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest
delegate:self];
if (!theConnection) {
// Release the receivedData object.
receivedData = nil;
// Inform the user that the connection failed.
}
転送はinitWithRequest:delegate:メッセージを受信するとすぐに始まります。デリゲートが
connectionDidFinishLoading:またはconnection:didFailWithError:メッセージを受信するまで
は、接続にcancelメッセージを送信することによって、いつでもキャンセルできます。
サーバがNSURLResponseオブジェクトを作成するために十分なデータを提供すると、デリゲートは
connection:didReceiveResponse:メッセージを受信します。デリゲートメソッドは、提供された
NSURLResponseオブジェクトを確認し、データの想定されるコンテンツ長、MIMEタイプ、提案され
るファイル名、およびサーバによって提供されるその他のメタデータを決定します。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
34
NSURLConnectionの使用
接続の作成
デリゲートは、1回の接続に対してconnection:didReceiveResponse:メッセージが複数回届いても
よいよう、備えておく必要があります。これはレスポンスがマルチパートMIMEエンコーディングの
場合に起こります。デリゲートは、connection:didReceiveResponse:メッセージを受信するたび
に、すべての進行結果をリセットし、それまでに受信したデータをすべて破棄する必要があります
(マルチパートレスポンスの場合を除く)。リスト 2-2の実装例では、呼び出されるたびに、受信さ
れたデータの長さを0にリセットするだけです。
リスト 2-2
connection:didReceiveResponse:の実装例
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse
*)response
{
// This method is called when the server has determined that it
// has enough information to create the NSURLResponse object.
// It can be called multiple times, for example in the case of a
// redirect, so each time we reset the data.
// receivedData is an instance variable declared elsewhere.
[receivedData setLength:0];
}
データが受信されると、デリゲートにconnection:didReceiveData:メッセージが定期的に送信され
ます。デリゲートの実装は、新たに受信されたデータを格納する役割を果たします。リスト 2-3の実
装例では、新しいデータはリスト 2-1 (34 ページ)で作成したNSMutableDataオブジェクトの最後に
追加されます。
リスト 2-3
connection:didReceiveData:の実装例
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// Append the new data to receivedData.
// receivedData is an instance variable declared elsewhere.
[receivedData appendData:data];
}
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
35
NSURLConnectionの使用
接続の作成
connection:didReceiveData:メソッドを使用して、接続の進行結果をユーザに提供することもでき
ます。まず、connection:didReceiveResponse:デリゲートメソッドのURLレスポンスオブジェクト
でexpectedContentLengthメソッドを呼び出すことによって、想定されるコンテンツ長(サーバに
よって提供される場合)を取得する必要があります。サーバから長さ情報が渡されなかった場合、
expectedContentLengthの戻り値はNSURLResponseUnknownLengthとなります。
転送中にエラーが発生すると、デリゲートにconnection:didFailWithError:メッセージが届きま
す。パラメータとして渡されるNSErrorオブジェクトには、エラーの詳細が明記されています。キー
NSURLErrorFailingURLStringErrorKeyを使用して、失敗したリクエストのURLも、ユーザ情報辞書
に記述されます。
デリゲートにconnection:didFailWithError:メッセージが届いた後は、指定された接続のデリゲー
トメッセージが届かなくなります。
リスト 2-4の例では、接続と受信されたデータが解放され、エラーがログに記録されます。
リスト 2-4
connection:didFailWithError:の実装例
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
// Release the connection and the data object
// by setting the properties (declared elsewhere)
// to nil.
Note that a real-world app usually
// requires the delegate to manage more than one
// connection at a time, so these lines would
// typically be replaced by code to iterate through
// whatever data structures you are using.
theConnection = nil;
receivedData = nil;
// inform the user
NSLog(@"Connection failed! Error - %@ %@",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
36
NSURLConnectionの使用
POST要求を行う
最後に、接続がリクエストの取得に成功すると、デリゲートにconnectionDidFinishLoading:メッ
セージが届きます。デリゲートは、それ以降、接続に対するメッセージを受信しなくなり、アプリ
ケーションはNSURLConnectionオブジェクトを解放できます。
リスト 2-5の実装例では、受信されたデータの長さがログに記録され、接続オブジェクトと受信され
たデータの両方が解放されます。
リスト 2-5
connectionDidFinishLoading:の実装例
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// do something with the data
// receivedData is declared as a property elsewhere
NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);
// Release the connection and the data object
// by setting the properties (declared elsewhere)
// to nil.
Note that a real-world app usually
// requires the delegate to manage more than one
// connection at a time, so these lines would
// typically be replaced by code to iterate through
// whatever data structures you are using.
theConnection = nil;
receivedData = nil;
}
これは、NSURLConnectionを使用するクライアントの最も単純な実装例です。追加のデリゲートメ
ソッドは、サーバリダイレクト、認証リクエスト、およびレスポンスのキャッシュ処理をカスタマイ
ズする機能を提供します。
POST要求を行う
HTTP/HTTPSのPOST要求を行う手順も、他のURL要求の場合とほとんど同じです(“認証例” (58 ペー
ジ)を参照)。違いは、まずNSMutableURLRequestオブジェクトを用意し、これを
initWithRequest:delegate:メソッドに渡すことです。
また、ボディーデータを組み立てることも必要です。その方法は3通りあります。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
37
NSURLConnectionの使用
POST要求を行う
●
●
●
メモリ上に作成した短いデータをアップロードする場合は、そのデータをURLエンコードしてく
ださい(“証明書なしでの続行” (57 ページ)を参照)。
ディスクに保存されているファイルデータをアップロードする場合は、NSMutableURLRequestの
setHTTPBodyStream:メソッドで、NSInputStreamオブジェクトから読み込んだデータをボディー
コンテンツとするよう指示します。
大容量のデータブロックを構築してアップロードする場合は、CFStreamCreateBoundPairでス
トリームの組を生成し、NSMutableURLRequestのsetHTTPBodyStream:メソッドで、一方のスト
リームをボディーコンテンツの供給源として指定します。もう一方のストリームにデータを書き
出せば、このデータを送信できることになります。
サーバ側の処理方法によっては、送信するデータをURLエンコードしなければならないかもしれ
ません(詳しくは“証明書なしでの続行” (57 ページ)を参照)。
URLローディングシステムは「100(Continue)」というHTTPの状態コードに対応しているので、データ
のアップロード先サーバも継続機能に対応していれば、認証エラーその他の障害が発生しても、中断
したところから続行できます。アップロードの継続機能を利用したいときは、リクエストのExpect:
ヘッダに「100-continue」を設定してください。
リスト 6-1に、POSTリクエストを行うようNSMutableURLRequestオブジェクトを設定する例を示しま
す。
リスト 2-6
POST要求を行うようNSMutableRequestオブジェクトを設定するコード例
// In body data for the 'application/x-www-form-urlencoded' content type,
// form fields are separated by an ampersand. Note the absence of a
// leading ampersand.
NSString *bodyData = @"name=Jane+Doe&address=123+Main+St";
NSMutableURLRequest *postRequest = [NSMutableURLRequest requestWithURL:[NSURL
URLWithString:@"https://www.apple.com"]];
// Set the request's content type to application/x-www-form-urlencoded
[postRequest setValue:@"application/x-www-form-urlencoded"
forHTTPHeaderField:@"Content-Type"];
// Designate the request a POST request and specify its body data
[postRequest setHTTPMethod:@"POST"];
[postRequest setHTTPBody:[NSData dataWithBytes:[bodyData UTF8String]
length:strlen([bodyData UTF8String])]];
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
38
NSURLConnectionの使用
完了ハンドラブロックを使ってデータを取得する
// Initialize the NSURLConnection and proceed as described in
// Retrieving the Contents of a URL
要求に他のコンテンツタイプを指定するには、setValue:forHTTPHeaderField:メソッドを使いま
す。その場合、当該コンテンツタイプに合わせて、適切な形式のボディーデータを与えてください。
POST要求の進捗状況を取得したい場合は、接続のデリゲートに
connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:メソッドを実
装します。これはアップロードの進行状況の正確な見積もりではありません。接続が失敗したりチャ
レンジ認証を発行したりする場合があるからです。
完了ハンドラブロックを使ってデータを取得する
NSURLConnectionクラスには、NSURLRequestオブジェクトで表されるリソースのコンテンツを、非
同期に取得する機能があります。結果が得られたとき、あるいはエラーやタイムアウトの際には、ブ
ロックが呼び出されます。これを実装するには、リクエストオブジェクト、完了ブロック、このブ
ロックを実行するNSOperationキューを引数として渡し、クラスメソッド
sendAsynchronousRequest:queue:completionHandler:を呼び出してください。リクエストが完了
し、あるいはエラーが発生すると、URLローディングシステムは、結果データまたはエラー情報を渡
してこのブロックを呼び出します。
成功した場合は、リクエストに応じたコンテンツが、コールバックハンドラブロックに、NSDataオ
ブジェクトおよびリクエストのNSURLResponseオブジェクトの形で渡されます。NSURLConnection
がURLを取得できなかった場合は、第3引数にNSErrorオブジェクトが渡されます。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
39
NSURLConnectionの使用
データを同期取得する
注意: このメソッドには重要な制限が2つあります。
●
●
認証が必要なリクエストに対するサポートが最小限です。接続を行うためにリクエスト
で認証が必要な場合、有効な証明書がNSURLCredentialStorageオブジェクトで既に利
用可能であるか、リクエストされたURLの一部として提供される必要があります。証明
書が利用できない場合や認証に失敗した場合、URLローディングシステムは、接続を処
理するNSURLProtocolサブクラスに
continueWithoutCredentialForAuthenticationChallenge:メッセージを送信する
ことによってレスポンスします。
レスポンスキャッシュのデフォルトの挙動を修正したり、サーバリダイレクトを受け入
れたりする方法がありません。接続がサーバリダイレクトを発行しようとすると、その
リダイレクトは常に受け付けられます。同様に、レスポンスデータは、プロトコル実装
によって提供されるデフォルトのサポートに応じて、キャッシュに格納されます。
NSURLSessionクラスには同様の機能が、こういった制限なしで実装されています。詳しく
は“NSURLSessionの使用” (15 ページ)を参照してください。
データを同期取得する
NSURLConnectionクラスには、クラスメソッドsendSynchronousRequest:returningResponse:error:
として、NSURLRequestオブジェクトで表されるリソースのコンテンツを同期取得する機能がありま
す。このメソッドの使用はお勧めしません。次のような厳格な制限があるからです。
●
●
●
コマンドラインツールの場合を除き、アプリケーションの主スレッドでは動作しないよう、コー
ドを記述する必要があります。
認証が必要なリクエストに対するサポートが最小限です。
レスポンスキャッシュのデフォルトの挙動を修正したり、サーバリダイレクトを受け入れたりす
る方法がありません。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
40
NSURLConnectionの使用
データを同期取得する
Important: データを同期取得する場合、アプリケーションの主メソッドでは件のコードがけっし
て 動作しないようにしなければなりません。ネットワークを介した処理は、完了までにいくらで
も長い時間がかかる可能性があります。このような処理を主スレッド上で同期実行すると、デー
タの受信が完了するか、エラーやタイムアウトになるまで、他の処理は実行が止まってしまいま
す。そのため非常に使い勝手が悪く、iOSがアプリケーションを強制停止する原因にもなりえま
す。
リクエストが成功すると、そのコンテンツはNSDataオブジェクトとして返され、リクエストの
NSURLResponseオブジェクトは参照によって返されます。NSURLConnectionがURLを取得できない場
合、このメソッドはnilおよびエラーの状況に応じたNSErrorのインスタンスを、対応する参照引数
を介して返します。
接続を行うためにリクエストで認証が必要な場合、有効な証明書がNSURLCredentialStorageオブ
ジェクトで既に利用可能であるか、リクエストされたURLの一部として提供される必要があります。
証明書が利用できない場合や認証に失敗した場合、URLローディングシステムは、接続を処理する
NSURLProtocolサブクラスにcontinueWithoutCredentialForAuthenticationChallenge:メッセー
ジを送信することによってレスポンスします。
同期接続がサーバリダイレクトを発行しようとすると、そのリダイレクトは常に受け付けられます。
同様に、レスポンスデータは、プロトコル実装によって提供されるデフォルトのサポートに応じて、
キャッシュに格納されます。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
41
NSURLDownloadの使用
OS Xでは、NSURLDownloadがアプリケーションにURLのコンテンツをディスクに直接ダウンロードす
る機能を提供します。NSURLConnectionと同様のインターフェイスを提供し、ファイルのダウンロー
ド先を指定する別のメソッドを追加します。NSURLDownloadは、MacBinary、BinHex、gzipなど、一般
的に使用されているエンコード方法をデコードすることもできます。NSURLConnectionとは異なり、
NSURLDownloadを使用してダウンロードされたデータはキャッシュシステムに格納されません。
アプリケーションがFoundationクラスの使用に限定されていない場合、WebKitフレームワークには、
WebDownload、認証用のユーザインターフェイスを提供するNSURLDownloadのサブクラスが含まれ
ます。
iOSにおける注意事項: NSURLDownloadクラスは、iOSでは使用できません。ファイルシステ
ムへの直接のダウンロードができないからです。代わりにNSURLSessionまたは
NSURLConnectionクラスを使用します。詳細については、“NSURLSessionの使用” (15 ペー
ジ)および“NSURLConnectionの使用” (33 ページ)を参照してください。
事前設定したダウンロード先へのダウンロード
NSURLDownloadの1つの使用パターンとして、ディスク上の事前設定したファイル名へのダウンロー
ドが挙げられます。アプリケーションがダウンロード先を認識している場合は、
setDestination:allowOverwrite:を使用して明示的に設定できます。NSURLDownloadへの複数の
setDestination:allowOverwrite:メッセージは無視されます。
ダウンロードは、initWithRequest:delegate:メッセージを受信次第、開始されます。デリゲート
がdownloadDidFinish:またはdownload:didFailWithError:メッセージを受信するまでは、ダウン
ロードにcancelメッセージを送信することによって、いつでもキャンセルできます。
リスト 3-1の例では、ダウンロード先を設定し、download:didFailWithError:および
downloadDidFinish:メソッドのみを実装するデリゲートをリクエストします。
リスト 3-1
ダウンロード先ファイルの場所を事前設定したNSURLDownloadの使用
- (void)startDownloadingURL:sender
{
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
42
NSURLDownloadの使用
事前設定したダウンロード先へのダウンロード
// Create the request.
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL
URLWithString:@"http://www.apple.com"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// Create the connection with the request and start loading the data.
NSURLDownload
*theDownload = [[NSURLDownload alloc] initWithRequest:theRequest
delegate:self];
if (theDownload) {
// Set the destination file.
[theDownload setDestination:@"/tmp" allowOverwrite:YES];
} else {
// inform the user that the download failed.
}
}
- (void)download:(NSURLDownload *)download didFailWithError:(NSError *)error
{
// Dispose of any references to the download object
// that your app might keep.
...
// Inform the user.
NSLog(@"Download failed! Error - %@ %@",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
- (void)downloadDidFinish:(NSURLDownload *)download
{
// Dispose of any references to the download object
// that your app might keep.
...
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
43
NSURLDownloadの使用
提案されたファイル名を使用したファイルのダウンロード
// Do something with the data.
NSLog(@"%@",@"downloadDidFinish");
}
デリゲートに追加のメソッドを実装することにより、認証、サーバリダイレクト、ファイルのデコー
ド処理をカスタマイズできます。
提案されたファイル名を使用したファイルのダウンロード
アプリケーションがダウンロードされたデータ自体からダウンロード先のファイル名を導出すること
が必要な場合があります。この場合、デリゲートメソッド
download:decideDestinationWithSuggestedFilename:および呼び出し
setDestination:allowOverwrite:を実装する必要があります。リスト 3-2の例では、提案された
ファイル名を使用してダウンロードされたファイルをデスクトップに保存します。
リスト 3-2
ダウンロードから導出されたファイル名でのNSURLDownloadの使用
- (void)startDownloadingURL:sender
{
// Create the request.
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL
URLWithString:@"http://www.apple.com/index.html"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// Create the download with the request and start loading the data.
NSURLDownload *theDownload = [[NSURLDownload alloc] initWithRequest:theRequest
delegate:self];
if (!theDownload) {
// Inform the user that the download failed.
}
}
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
44
NSURLDownloadの使用
提案されたファイル名を使用したファイルのダウンロード
- (void)download:(NSURLDownload *)download
decideDestinationWithSuggestedFilename:(NSString *)filename
{
NSString *destinationFilename;
NSString *homeDirectory = NSHomeDirectory();
destinationFilename = [[homeDirectory stringByAppendingPathComponent:@"Desktop"]
stringByAppendingPathComponent:filename];
[download setDestination:destinationFilename allowOverwrite:NO];
}
- (void)download:(NSURLDownload *)download didFailWithError:(NSError *)error
{
// Dispose of any references to the download object
// that your app might keep.
...
// Inform the user.
NSLog(@"Download failed! Error - %@ %@",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
- (void)downloadDidFinish:(NSURLDownload *)download
{
// Dispose of any references to the download object
// that your app might keep.
...
// Do something with the data.
NSLog(@"%@",@"downloadDidFinish");
}
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
45
NSURLDownloadの使用
ダウンロードの進行状況の表示
ダウンロードされたファイルは、index.htmlという名前でユーザのデスクトップに格納されます。
この名前は、ダウンロードされたコンテンツから派生したものでした。NOを
setDestination:allowOverwrite:に渡すと、ダウンロードによって既存のファイルが上書きされ
なくなります。ファイル名の後に連番を挿入することによって、一意のファイル名が作成されます。
たとえば、index-1.htmlなどです。
download:didCreateDestination:メソッドを実装すると、ディスク上にファイルが作成されたと
きにデリゲートに通知されます。このメソッドはまた、ダウンロードが保存される最終的なファイル
名を決定する機会をアプリケーションに与えます。
リスト 3-3の例では、最終的なファイル名がログに記録されます。
リスト 3-3
download:didCreateDestination:を使用した最終的なファイル名のログ記録
-(void)download:(NSURLDownload *)download didCreateDestination:(NSString *)path
{
// path now contains the destination path
// of the download, taking into account any
// unique naming caused by -setDestination:allowOverwrite:
NSLog(@"Final file destination: %@",path);
}
このメッセージは、デリゲートにdownload:shouldDecodeSourceDataOfMIMEType:および
download:decideDestinationWithSuggestedFilename:メッセージにレスポンスする機会が与えら
れた後、デリゲートに送信されます。
ダウンロードの進行状況の表示
ダウンロードの進行状況は、デリゲートメソッドdownload:didReceiveResponse:および
download:didReceiveDataOfLength:を実装することによって確認できます。
download:didReceiveResponse:メソッドは、NSURLResponseから想定されるコンテンツ長を決定
する機会をデリゲートに与えます。デリゲートは、このメッセージを受信するたびに、進行状況をリ
セットする必要があります。
リスト 3-4の実装例では、これらのメソッドを使用してユーザに進行状況のフィードバックを提供す
る方法を示します。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
46
NSURLDownloadの使用
ダウンロードの進行状況の表示
リスト 3-4
ダウンロードの進行状況の表示
- (void)setDownloadResponse:(NSURLResponse *)aDownloadResponse
{
// downloadResponse is an instance variable defined elsewhere.
downloadResponse = aDownloadResponse;
}
- (void)download:(NSURLDownload *)download didReceiveResponse:(NSURLResponse
*)response
{
// Reset the progress, this might be called multiple times.
// bytesReceived is an instance variable defined elsewhere.
bytesReceived = 0;
// Store the response to use later.
[self setDownloadResponse:response];
}
- (void)download:(NSURLDownload *)download didReceiveDataOfLength:(unsigned)length
{
long long expectedLength = [[self downloadResponse] expectedContentLength];
bytesReceived = bytesReceived + length;
if (expectedLength != NSURLResponseUnknownLength) {
// If the expected content length is
// available, display percent complete.
float percentComplete = (bytesReceived/(float)expectedLength)*100.0;
NSLog(@"Percent complete - %f",percentComplete);
} else {
// If the expected content length is
// unknown, just log the progress.
NSLog(@"Bytes received - %d",bytesReceived);
}
}
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
47
NSURLDownloadの使用
ダウンロードの再開
デリゲートは、download:didReceiveDataOfLength:メッセージの受信を開始する前に、
download:didReceiveResponse:メッセージを受信します。
ダウンロードの再開
場合によっては、進行中にキャンセルされたか失敗したダウンロードを再開できます。これを行うに
は、まず、NOをダウンロードのsetDeletesFileUponFailure:メソッドに渡すことによって、元の
ダウンロードが失敗時にそのデータを削除していないことを確認します。元のダウンロードに失敗し
た場合は、resumeDataメソッドを使用してそのデータを取得できます。その後、
initWithResumeData:delegate:path:メソッドを使用して新しいダウンロードを初期化できます。
ダウンロードが再開されると、ダウンロードのデリゲートは
download:willResumeWithResponse:fromByte:メッセージを受信します。
ダウンロードを再開できるのは、接続のプロトコルと、ダウンロードされるファイルのMIMEタイプ
の両方が再開をサポートしている場合のみです。canResumeDownloadDecodedWithEncodingMIMEType:
メソッドを使用して、ファイルのMIMEタイプがサポートされているかどうかを確認できます。
エンコードされたファイルのデコード
NSURLDownloadは、MacBinary、BinHex、gzipといったファイル形式のデコードをサポートしていま
す。NSURLDownloadは、ファイルがサポートされている形式でエンコードされていることを確認する
と、デリゲートへのdownload:shouldDecodeSourceDataOfMIMEType:メッセージの送信を試行しま
す。デリゲートがこのメソッドを実装すると、渡されたMIMEタイプを確認し、ファイルがデコード
される場合はYES を返します。
リスト 3-5の例では、ファイルのMIMEタイプが比較され、MacBinaryおよびBinHexのエンコードされた
コンテンツのデコードが許可されます。
リスト 3-5
download:shouldDecodeSourceDataOfMIMEType:の実装例
- (BOOL)download:(NSURLDownload *)download
shouldDecodeSourceDataOfMIMEType:(NSString *)encodingType
{
BOOL shouldDecode = NO;
if ([encodingType isEqual:@"application/macbinary"]) {
shouldDecode = YES;
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
48
NSURLDownloadの使用
エンコードされたファイルのデコード
} else if ([encodingType isEqual:@"application/binhex"]) {
shouldDecode = YES;
} else if ([encodingType isEqual:@"application/x-gzip"]) {
shouldDecode = NO;
}
return shouldDecode;
}
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
49
URLデータのエンコード
文字列をURLエンコード/デコードするためには、Core Foundationの
CFURLCreateStringByAddingPercentEscapes関数、
CFURLCreateStringByReplacingPercentEscapesUsingEncoding関数を使います。8ビットコード
の最上位ビットが1である文字(0x80~0xff)およびASCIIの非印字文字(制御文字)以外に、URLエ
ンコードする文字を指定できます。
RFC 3986によれば、URLにおいて予約されている文字は次の通りです。
reserved
= gen-delims / sub-delims
gen-delims
= ":" / "/" / "?" / "#" / "[" / "]" / "@"
sub-delims
= "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
したがって、UTF-8の文字列をエンコードしてURLに埋め込めるようにするコードは、たとえば次のよ
うになります。
CFStringRef originalString = ...
CFStringRef encodedString = CFURLCreateStringByAddingPercentEscapes(
kCFAllocatorDefault,
originalString,
NULL,
CFSTR(":/?#[]@!$&'()*+,;="),
kCFStringEncodingUTF8);
URLの一部をデコードするためには、あらかじめ構成要素(フィールドやパス部分)に分割しなけれ
ばなりません。デコードしなければ、たとえばエンコード済みのアンパサンド(元々のコンテンツの
一部であったもの)と、フィールドの末尾を表していた「生の」アンパサンドを区別できません。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
50
URLデータのエンコード
URLを構成要素に分割すれば、次のようにしてデコードできます。
CFStringRef decodedString = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(
kCFAllocatorDefault,
encodedString,
CFSTR(""),
kCFStringEncodingUTF8);
Important: NSStringクラスには「パーセントエスケープ」を行うメソッドがいくつかあります
が、通常は使わない でください。このメソッドは、いくつかの文字列をアンパサンド区切りで連
結した文字列が渡される、と想定しています。そのため、元々の文字列にアンパサンドが含まれ
ている場合、正しくURLエンコードできません。うっかりこのメソッドを使うと、URL文字列イン
ジェクション攻撃に対して脆弱になる恐れがあります(ほかの箇所で不正なURLを処理する方法に
も依存)。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
51
リダイレクトとその他のリクエスト変更の処
理
サーバがリクエストに応答すると、クライアントが別のURLにリクエストを送り直す必要がある旨伝
える、という形でリダイレクトが発生します。NSURLSession、NSURLConnection、NSURLDownload
の各クラスは、これが発生するとそれぞれのデリゲートに通知します。
リダイレクトを処理するため、URLローディングクラスのデリゲートには、次のいずれかのデリゲー
トメソッドを実装しなければなりません。
●
NSURLSessionの場合は、
URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:デリゲー
トメソッドを実装します。
●
NSURLConnectionの場合は、connection:willSendRequest:redirectResponse:デリゲートメ
ソッドを実装します。
●
NSURLDownloadの場合は、download:willSendRequest:redirectResponse:デリゲートメソッ
ドを実装します。
上記のメソッドで、デリゲートはリダイレクトを発生させた新しいリクエストとレスポンスを確認
し、NSURLSessionの完了ハンドラを介して、またはNSURLConnectionおよびNSURLDownloadの戻り
値として、新しいリクエストオブジェクトを返すことができます。
デリゲートは次のいずれかを実行できます。
●
指定されたリクエストを返すことによりリダイレクトを許可する。
●
別のURLを指し示す新しいリクエストを作成し、そのリクエストを返す。
●
nilを返すことによって、リダイレクトを拒否し、あるいは接続から既存のデータを受信する。
さらに、デリゲートはリダイレクトと接続の両方をキャンセルできます。NSURLSessionでは、デリ
ゲートはcancelメッセージをタスクオブジェクトに送信することによってこれを行います。
NSURLConnectionまたはNSURLDownload APIでは、cancelメッセージをNSURLConnectionまたは
NSURLDownloadオブジェクトに送信することによってこれを行います。
デリゲートはまた、リクエストを処理するNSURLProtocolサブクラスが形式を標準化するために
NSURLRequestを変更した場合に、connection:willSendRequest:redirectResponse:メッセージ
を受信します。たとえば、http://www.apple.comに対するリクエストをhttp://www.apple.com/
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
52
リダイレクトとその他のリクエスト変更の処理
に変更するなどです。これが行われるのは、標準化されたリクエストのバージョンがキャッシュ管理
に使用されるためです。このような特殊な場合には、デリゲートに渡されるレスポンスがnilであり、
デリゲートは指定されたリクエストを返すだけです。
リスト 5-1の実装例では、標準的な変更は許可され、サーバのリダイレクトはすべて拒否されます。
リスト 5-1
connection:willSendRequest:redirectResponse:の実装例
#if FOR_NSURLSESSION
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
willPerformHTTPRedirection:(NSHTTPURLResponse *)redirectResponse
newRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSURLRequest *))completionHandler
#elif FOR_NSURLCONNECTION
-(NSURLRequest *)connection:(NSURLConnection *)connection
willSendRequest:(NSURLRequest *)request
redirectResponse:(NSURLResponse *)redirectResponse
#else // FOR_NSURLDOWNLOAD
-(NSURLRequest *)download:(NSURLConnection *)connection
willSendRequest:(NSURLRequest *)request
redirectResponse:(NSURLResponse *)redirectResponse
#endif
{
NSURLRequest *newRequest = request;
if (redirectResponse) {
newRequest = nil;
}
#if FOR_NSURLSESSION
completionHandler(newRequest);
#else
return newRequest;
#endif
}
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
53
リダイレクトとその他のリクエスト変更の処理
デリゲートがデリゲートメソッドを処理する適切なリダイレクトを実装しない場合、標準的な変更と
サーバのリダイレクトはすべて許可されます。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
54
チャレンジ認証とTLSチェーン認証
NSURLRequestオブジェクトは、チャレンジ認証、または接続先のサーバからの証明書のリクエスト
を発行することがよくあります。NSURLSession、NSURLConnection、NSURLDownloadの各クラスは
デリゲートに対して、リクエストがチャレンジ認証を発行するときに、それに応じて機能できるよう
に通知します。
Important: サーバのレスポンスにWWW-Authenticateヘッダがある場合を除き、URLローディング
システムの各クラスが、それぞれのデリゲートを呼び出してリクエストチャレンジを処理するこ
とはありません。プロキシ認証、TLS信頼検証など、他の種類の認証はこのヘッダを要しません。
チャレンジ認証への対応方法の決定
NSURLRequestオブジェクトに認証が必要な場合、アプリケーションにおけるチャレンジの挙動は、
リクエストを処理するのがNSURLSession、NSURLConnection、NSURLDownloadのどれであるかに
よって異なります。
●
●
●
リクエストがNSURLSessionオブジェクトに関連付けられている場合、認証タイプにかかわらず、
すべての認証リクエストがデリゲートに渡されます。
リクエストがNSURLConnectionまたはNSURLDownloadオブジェクトに関連付けられている場合、
そのオブジェクトのデリゲートはconnection:canAuthenticateAgainstProtectionSpace:(ま
たはdownload:canAuthenticateAgainstProtectionSpace:)メッセージを受信します。これ
により、デリゲートに対する認証を試行する前に、デリゲートがプロトコルや認証メソッドなど
のサーバのプロパティを分析できるようになります。デリゲートでサーバの予約領域に対して認
証する準備ができていない場合は、NOを返すことができ、ユーザのキーチェーンの情報による認
証が試行されます。
NSURLConnectionまたはNSURLDownloadオブジェクトのデリゲートで
connection:canAuthenticateAgainstProtectionSpace:(または
download:canAuthenticateAgainstProtectionSpace:)メソッドが実装されておらず、予約
領域でクライアント証明書認証またはサーバ信用認証が使用されていない場合、システムはNOを
返した場合のように動作します。システムは、他のすべての認証タイプに対してYESを返した場
合のように動作します。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
55
チャレンジ認証とTLSチェーン認証
チャレンジ認証への対応
次に、デリゲートが認証の処理に応じ、リクエストされたURLの一部として、または共有されている
NSURLCredentialStorageにおいて、有効な証明書を入手できない場合、デリゲートは次のいずれか
のメッセージを受信します。
URLSession:didReceiveChallenge:completionHandler:
URLSession:task:didReceiveChallenge:completionHandler:
connection:didReceiveAuthenticationChallenge:
download:didReceiveAuthenticationChallenge:
接続され続けるにようにするために、デリゲートには次の3つのオプションがあります。
●
認証証明書を提供する.
●
証明書なしで続行を試行する.
●
チャレンジ認証をキャンセルする.
正しいアクション順序の決定を支援するために、メソッドに渡されたNSURLAuthenticationChallenge
インスタンスは、チャレンジ認証をトリガしたもの、認証チャンレンジの試行回数、以前に試行され
た証明書、証明書が必要なNSURLProtectionSpace、チャンレンジの送信者についての情報が含まれ
ます。
(ユーザがサーバ上でパスワードを変更したなどのため)チャレンジ認証が以前に認証を試行して失
敗していた場合は、チャレンジ認証でproposedCredentialを呼び出すことによって試行された証明
書を入手できます。次にデリゲートはこれらの証明書を使用して、ユーザに表示されるダイアログに
データを読み込みます。
チャレンジ認証でpreviousFailureCountを呼び出すと、異なる認証プロトコルの認証も含めて、以
前の認証試行合計数が返されます。デリゲートは、以前に提供した証明書で失敗するかどうかを判断
するためや、最大認証試行数を制限するために、この情報をユーザに提供できます。
チャレンジ認証への対応
次に示すのは、connection:didReceiveAuthenticationChallenge:デリゲートメソッドに対応で
きる3つの方法です。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
56
チャレンジ認証とTLSチェーン認証
チャレンジ認証への対応
証明書の提供
認証を試行するために、アプリケーションによってサーバで想定される形式の認証情報が含まれる
NSURLCredentialオブジェクトが作成されます。提供されたチャレンジ認証の予約領域で
authenticationMethodを呼び出すことによって、サーバの認証メソッドを決定できます。
NSURLCredentialによってサポートされる認証メソッドをいくつか挙げます。
●
●
●
●
HTTP Basic認証(NSURLAuthenticationMethodHTTPBasic)では、ユーザ名とパスワードが必要
です。必要な情報を入力するようにユーザを促し、credentialWithUser:password:persistence:
によってNSURLCredentialオブジェクトを作成します。
HTTP Digest認証(NSURLAuthenticationMethodHTTPDigest)では、Basic認証と同様に、ユーザ
名およびパスワードが必要です(Digestは自動的に生成されます)。必要な情報を入力するよう
にユーザを促し、credentialWithUser:password:persistence:によってNSURLCredentialオ
ブジェクトを作成します。
クライアント証明書認証(NSURLAuthenticationMethodClientCertificate)では、システム
IDと、サーバでの認証に必要なすべての証明書が必要です。
credentialWithIdentity:certificates:persistence:によってNSURLCredentialオブジェク
トを作成します。
サーバ信用認証(NSURLAuthenticationMethodServerTrust)では、チャレンジ認証の予約領
域によって提供される信用が必要です。credentialForTrust:によってNSURLCredentialオブ
ジェクトを作成します。
NSURLCredentialオブジェクトの作成後、次を行います。
●
NSURLSessionの場合は、提供された完了ハンドラブロックを使用して、チャレンジ認証の送信
者にオブジェクトを渡します。
●
NSURLConnectionおよびNSURLDownloadの場合は、
useCredential:forAuthenticationChallenge:によってチャレンジ認証の送信者にオブジェク
トを渡します。
証明書なしでの続行
デリゲートがチャレンジ認証の証明書を提供しないことを選択した場合は、証明書なしでの続行を試
行できます。
●
NSURLSessionの場合は、提供された完了ハンドラブロックを使用して、次のいずれかの値を渡
します。
NSURLSessionAuthChallengePerformDefaultHandlingでは、デリゲートがチャレンジを処理
するためにデリゲートメソッドを提供しなかったかのようにリクエストが処理されます。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
57
チャレンジ認証とTLSチェーン認証
チャレンジ認証への対応
NSURLSessionAuthChallengeRejectProtectionSpaceでは、チャレンジが拒否されます。サー
バのレスポンスにより許可された認証の種類によりますが、URLローディングクラスはこのデリ
ゲートメソッドを複数回呼び出して、保護を強化することがあります。
NSURLConnectionおよびNSURLDownloadの場合は、[challenge sender]で
●
continueWithoutCredentialsForAuthenticationChallenge:を呼び出します。
証明書なしで続行すると、プロトコルの実装に応じて、接続が失敗して
connectionDidFailWithError:メッセージが表示されるか、認証が不要な代わりのURLコンテン
ツが返されます。
接続のキャンセル
デリゲートでは、チャレンジ認証のキャンセルを選択することもできます。
NSURLSessionの場合は、NSURLSessionAuthChallengeCancelAuthenticationChallengeを渡
●
して完了ハンドラブロックを提供します。
NSURLConnectionまたはNSURLDownloadの場合は、[challenge sender]で
●
cancelAuthenticationChallenge:を呼び出します。デリゲートは、ユーザにフィードバックを
提供する機会を提供する、connection:didCancelAuthenticationChallenge:メッセージを受
信します。
認証例
リスト 6-1に示す実装では、アプリケーションの環境設定によって指定されるユーザ名とパスワード
を使用してNSURLCredentialインスタンスを作成することによって、チャレンジの認証が試行されま
す。認証が以前に失敗した場合、認証チャンレンジはキャンセルされ、ユーザに通知されます。
リスト 6-1
connection:didReceiveAuthenticationChallenge:デリゲートメソッドを使用した例
-(void)connection:(NSURLConnection *)connection
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge previousFailureCount] == 0) {
NSURLCredential *newCredential;
newCredential = [NSURLCredential credentialWithUser:[self preferencesName]
password:[self preferencesPassword]
persistence:NSURLCredentialPersistenceNone];
[[challenge sender] useCredential:newCredential
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
58
チャレンジ認証とTLSチェーン認証
カスタムTLSチェーン認証の実行
forAuthenticationChallenge:challenge];
} else {
[[challenge sender] cancelAuthenticationChallenge:challenge];
// inform the user that the user name and password
// in the preferences are incorrect
[self showPreferencesCredentialsAreIncorrectPanel:self];
}
}
デリゲートがconnection:didReceiveAuthenticationChallenge:を実装しておらず、リクエスト
で認証が必要な場合、有効な証明書が既にURL証明書ストレージで利用可能であるか、リクエストさ
れたURLの一部として提供される必要があります。証明書を入手できないか、認証に失敗した場合、
基本的な実装によってcontinueWithoutCredentialForAuthenticationChallenge:メッセージが
送信されます。
カスタムTLSチェーン認証の実行
NSURLに関係する一連のAPIでは、TLSチェーン認証を処理するのはアプリケーション側の認証デリゲー
トメソッドですが、サーバに証明書を渡してユーザ(やアプリケーション)を認証するのではなく、
TLSハンドシェイクの際にサーバから渡された証明書をアプリケーション側で検証し、URLローディン
グシステムに対して、この証明書を受理するか拒否するか通知するようになっています。
標準的でない方法(テストのために特定の自己署名証明書を受け入れるなど)でチェーン検証を実行
する必要がある場合は、アプリケーションが次を実行する必要があります。
●
NSURLSessionの場合は、URLSession:didReceiveChallenge:completionHandler:または
URLSession:task:didReceiveChallenge:completionHandler:デリゲートメソッドのいずれ
かを実装します。両方を実装すると、セッションレベルのメソッドが認証を処理する役割を果た
します。
●
NSURLConnectionおよびNSURLDownloadの場合は、予約領域に認証タイプ
NSURLAuthenticationMethodServerTrustがあれば、
connection:canAuthenticateAgainstProtectionSpace:または
download:canAuthenticateAgainstProtectionSpace:メソッドを実装し、YESを返します。
次に、認証を処理するconnection:didReceiveAuthenticationChallenge:または
download:didReceiveAuthenticationChallenge:メソッドを実装します。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
59
チャレンジ認証とTLSチェーン認証
カスタムTLSチェーン認証の実行
認証ハンドラデリゲートメソッド内で、チャレンジ予約領域に認証タイプ
NSURLAuthenticationMethodServerTrustがあるかどうかを確認し、もしあれば、予約領域から
serverTrust情報を取得します。
詳細およびコードスニペット(NSURLConnectionに基づく)の詳細については、“Overriding TLS Chain
Validation Correctly”を参照してください。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
60
Understanding Cache Access
The URL loading system provides a composite on-disk and in-memory cache of responses to requests. This
cache allows an application to reduce its dependency on a network connection and increase its performance.
Using the Cache for a Request
An NSURLRequest instance specifies how the local cache is used by setting the cache policy to one of the
NSURLRequestCachePolicy values: NSURLRequestUseProtocolCachePolicy,
NSURLRequestReloadIgnoringCacheData, NSURLRequestReturnCacheDataElseLoad, or
NSURLRequestReturnCacheDataDontLoad.
The default cache policy for an NSURLRequest instance is NSURLRequestUseProtocolCachePolicy. The
NSURLRequestUseProtocolCachePolicy behavior is protocol specific and is defined as being the best
conforming policy for the protocol.
Setting the cache policy to NSURLRequestReloadIgnoringCacheData causes the URL loading system to
load the data from the originating source, ignoring the cache completely.
The NSURLRequestReturnCacheDataElseLoad cache policy causes the URL loading system to use cached
data, ignoring its age or expiration date, and to load the data from the originating source only if there is no
cached version.
The NSURLRequestReturnCacheDataDontLoad policy allows an application to specify that only data in the
cache should be returned. Attempting to create an NSURLConnection or NSURLDownload instance with this
cache policy returns nil immediately if the response is not in the local cache. This is similar in function to an
“offline” mode and never brings up a network connection.
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
61
Understanding Cache Access
Cache Use Semantics for the HTTP Protocol
Note: Currently, only responses to HTTP and HTTPS requests are cached. The FTP and file protocols
attempt to access the originating source as allowed by the cache policy. Custom NSURLProtocol
classes can optionally provide caching.
Cache Use Semantics for the HTTP Protocol
The most complicated cache use situation is when a request uses the HTTP protocol and has set the cache
policy to NSURLRequestUseProtocolCachePolicy.
If an NSCachedURLResponse does not exist for the request, then the URL loading system fetches the data
from the originating source.
If a cached response exists for the request, the URL loading system checks the response to determine if it
specifies that the contents must be revalidated.
If the contents must be revalidated, the URL loading system makes a HEAD request to the originating source
to see if the resource has changed. If it has not changed, then the URL loading system returns the cached
response. If it has changed, the URL loading system fetches the data from the originating source.
If the cached response doesn’t specify that the contents must be revalidated, the URL loading system examines
the maximum age or expiration specified in the cached response. If the cached response is recent enough,
then the URL loading system returns the cached response. If the response is stale, the URL loading system
makes a HEAD request to the originating source to determine whether the resource has changed. If so, the
URL loading system fetches the resource from the originating source. Otherwise, it returned the cached response.
RFC 2616, Section 13 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13) specifies the semantics
involved in detail.
Controlling Caching Programmatically
By default, the data for a connection is cached based on the request’s cache policy, as interpreted by the
NSURLProtocol subclass that handles the request.
If your app needs more precise programmatic control over caching (and if the protocol supports caching), you
can implement a delegate method that allows your app to determine on a per-request basis whether a particular
response should be cached.
●
For NSURLSession data and upload tasks, implement the
URLSession:dataTask:willCacheResponse:completionHandler: method.
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
62
Understanding Cache Access
Controlling Caching Programmatically
This delegate method is called only for data and upload tasks. The caching policy for download tasks is
determined by the specified cache policy exclusively.
For NSURLConnection, implement the connection:willCacheResponse: method.
●
For NSURLSession, your delegate method calls a completion handler block to tell the session what to cache.
For NSURLConnection, your delegate method returns the object that the connection should cache.
In either case, the delegate typically provides one the following values:
●
The provided response object to allow caching
●
A newly created response object to cache a modified response—for example, a response with a storage
policy that allows caching to memory but not to disk
●
NULL to prevent caching
Your delegate method can also insert objects into the userInfo dictionary associated with an
NSCachedURLResponse object, causing those objects to be stored in the cache as part of the response.
Important: If you are using NSURLSession and you implement this delegate method, your delegate
method must always call the provided completion handler. Otherwise, your app leaks memory.
The example in リスト 7-1 prevents the on-disk caching of HTTPS responses. It also adds the current date to
the user info dictionary for responses that are cached.
リスト 7-1
Example connection:withCacheResponse: implementation
-(NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
NSCachedURLResponse *newCachedResponse = cachedResponse;
NSDictionary *newUserInfo;
newUserInfo = [NSDictionary dictionaryWithObject:[NSDate date]
forKey:@"Cached Date"];
if ([[[[cachedResponse response] URL] scheme] isEqual:@"https"]) {
#if ALLOW_IN_MEMORY_CACHING
newCachedResponse = [[NSCachedURLResponse alloc]
initWithResponse:[cachedResponse response]
data:[cachedResponse data]
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
63
Understanding Cache Access
Controlling Caching Programmatically
userInfo:newUserInfo
storagePolicy:NSURLCacheStorageAllowedInMemoryOnly];
#else // !ALLOW_IN_MEMORY_CACHING
newCachedResponse = nil
#endif // ALLOW_IN_MEMORY_CACHING
} else {
newCachedResponse = [[NSCachedURLResponse alloc]
initWithResponse:[cachedResponse response]
data:[cachedResponse data]
userInfo:newUserInfo
storagePolicy:[cachedResponse storagePolicy]];
}
return newCachedResponse;
}
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
64
cookieとカスタムプロトコル
cookieを追加/削除する、cookieを受け入れるかどうか判断するなど、アプリケーションがプログラム
でcookieを管理する場合は、“cookieストレージ” (65 ページ)を参照してください。
アプリケーションがNSURLでネイティブにサポートされていないURLベースのプロトコルをサポート
する必要がある場合は、必要なサポートを提供する独自のカスタムプロトコルクラスを登録できま
す。詳しくは、“プロトコルのサポート” (66 ページ)を参照してください。
cookieストレージ
HTTPプロトコルの処理状態を把握しない性質により、クライアントは多くの場合、cookieを使って、
データアクセスURLリクエストの永続ストレージを提供します。URLローディングシステムは、cookie
の作成や管理のほか、HTTPリクエストの一部としてcookieを送信し、あるいはWebサーバのレスポン
スを分析してcookieを受信するためのインターフェイスを備えています。
NSHTTPCookieクラスは、cookieをカプセル化し、一般的なcookieの属性の多くに対するアクセス機構
を提供します。また、HTTP cookieヘッダをNSHTTPCookieインスタンスに変換し、NSHTTPCookieイン
スタンスをNSURLRequestでの使用に適したヘッダに変換するメソッドも提供します。リクエストで
cookieを送信しないように指定されていない限り、URLローディングシステムは、NSURLRequestオブ
ジェクトに適した格納されているcookieを自動的に送信します。同様に、NSURLResponseオブジェク
トで返されるcookieは、現在のcookie受け入れポリシーに従って受け入れられます。
NSHTTPCookieStorageクラスは、すべてのアプリケーションで共有されているNSHTTPCookieオブ
ジェクトのコレクションを管理するためのインターフェイスを提供します。
iOSにおける注意事項: cookieはiOSのアプリケーション間では共有されません。
NSHTTPCookieStorageでは、アプリケーションがcookie受け入れポリシーを指定できます。cookie受
け入れポリシーは、cookieが常に受け入れられるべきか、受け入れられないべきか、またはメインド
キュメントURLと同じドメインからのみ受け入れられるべきかを制御します。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
65
cookieとカスタムプロトコル
プロトコルのサポート
注意: アプリケーションのcookie受け入れポリシーを変更すると、実行中の他のすべてのア
プリケーションのcookie受け入れポリシーに影響します。
別のアプリケーションがcookieストレージまたはcookie受け入れポリシーを変更すると、
NSHTTPCookieStorageは、NSHTTPCookieManagerCookiesChangedNotificationおよび
NSHTTPCookieStorageAcceptPolicyChangedNotificationの通知をポストすることによって、ア
プリケーションに通知します。
詳細については、『NSHTTPCookieStorage Class Reference 』および『NSHTTPCookie Class Reference 』を参
照してください。
プロトコルのサポート
URLローディングシステムの設計では、クライアントアプリケーションがデータ転送のためにサポー
トされているプロトコルを拡張できます。URLローディングシステムでは、http、https、file、
ftp、およびdataプロトコルがネイティブにサポートされています。
NSURLProtocolをサブクラスを定義し、NSURLProtocolのregisterClass:クラスメソッドを使用し
てURLローディングシステムに新しいクラスを登録することによって、カスタムプロトコルを実装で
きます。NSURLSession、NSURLConnection、またはNSURLDownloadオブジェクトがNSURLRequest
オブジェクトに対する接続を開始すると、URLローディングシステムは、登録されたクラスをそれぞ
れ登録とは逆順で参照します。canInitWithRequest:メッセージに対してYESを返す最初のクラス
は、リクエストを処理するために使用されます。
カスタムプロトコルでそのリクエストまたはレスポンスのために追加のプロパティが必要な場合は、
それらのプロパティに対するアクセス機構を提供するNSURLRequest、NSMutableURLRequest、
NSURLResponseクラスを作成することによって、それらをサポートします。NSURLProtocolクラス
は、それらのアクセス機構のプロパティ値を設定および取得するためのメソッドを提供します。
URLローディングシステムは、接続の開始および完了時にNSURLProtocolインスタンスを作成および
リリースする役割を果たします。アプリケーションは、NSURLProtocolのインスタンスを直接作成す
べきではありません。
NSURLProtocolサブクラスがURLローディングシステムによって初期化されると、
NSURLProtocolClientプロトコルに準拠するクライアントオブジェクトが提供されます。レスポン
スの作成、データの受信、新しいURLのリダイレクト、認証のリクエスト、読み込みの完了が行われ
ると、NSURLProtocolサブクラスはNSURLProtocolClientプロトコルからクライアントオブジェク
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
66
cookieとカスタムプロトコル
プロトコルのサポート
トにメッセージを送信して、URLローディングシステムにそのアクションを通知します。カスタムプ
ロトコルで認証がサポートされる場合、そのプロトコルはNSURLAuthenticationChallengeSender
プロトコルに準拠する必要があります。
詳細については、『NSURLProtocol Class Reference 』を参照してください。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
67
URLセッションのライフサイクル
NSURLSession APIには、システム提供のデリゲートと独自のデリゲートの2通りの使用方法がありま
す。一般に、アプリケーションが次のいずれかを行う場合は、独自のデリゲートを使用する必要があ
ります。
●
アプリケーションが動作していないときに、バックグラウンドセッションを使用してコンテンツ
をダウンロードまたはアップロードする。
●
カスタム認証を実行する。
●
カスタムSSL証明書の検証を実行する。
●
●
サーバが返すMIMEタイプまたはその他の同様の基準に基づいて、転送をディスクにダウンロード
すべきか、表示すべきかを決定する。
(NSDataオブジェクトの対極にあるものとして)ボディストリームからデータをアップロードす
る
●
プログラムでキャッシュを制限する。
●
プログラムでHTTPリダイレクトを制限する。
アプリケーションでこれらの設定のいずれも不要な場合は、システム提供のデリゲートを使用できま
す。選択した方法に応じて、次のいずれかの節を参照してください。
●
●
“システム提供のデリゲートを使用したURLセッションのライフサイクル” (69 ページ)では、
コードがURLセッションを作成および使用する仕組みの概要を示します。オブジェクトを設定お
よび使用するためにコードが行う必要のあることの概要が示されているため、独自のデリゲート
を書き込む場合でもこの節を参照してください。
“カスタムデリゲートを使用したURLセッションのライフサイクル” (70 ページ)では、URLセッ
ションの操作におけるすべての手順の概要を示します。セッションがそのデリゲートを使用して
対話する仕組みを理解するには、この節を参照してください。この節では、特に、各デリゲート
メソッドが呼び出されるタイミングについて説明しています。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
68
URLセッションのライフサイクル
システム提供のデリゲートを使用したURLセッションのライフサイクル
システム提供のデリゲートを使用したURLセッションのライフ
サイクル
デリゲートオブジェクトを指定せずにNSURLSessionクラスを使用している場合、システム提供のデ
リゲートは細部の多くを処理します。NSURLSessionおよびシステム組み込みのデリゲートを利用す
る場合について、アプリケーションに実装するべき基本的なメソッド呼び出しと、システム側から呼
び出される完了ハンドラの流れを示します。
1.
セッション設定を作成します。フォアグラウンドセッションの場合、この設定には一意の識別子
を含める必要があります。その識別子を格納し、アプリケーションがクラッシュまたは終了ある
いは一時停止した場合はそれを使用してセッションと関連付け直します。
2.
セッションを作成し、設定オブジェクトとnilデリゲートを指定します。
3.
セッション内でそれぞれがリソースリクエストを表すタスクオブジェクトを作成します。
各タスクは、一時停止状態から開始されます。アプリケーションは、タスクでresumeを呼び出し
た後、指定されたリソースのダウンロードを開始します。
タスクオブジェクトは、NSURLSessionTaskのサブクラスです。どのような動作にしたいかによっ
て、NSURLSessionDataTask、NSURLSessionUploadTask、NSURLSessionDownloadTaskのいず
れかを選択します。これらのオブジェクトはNSURLConnectionオブジェクトに似ていますが、よ
り詳細に制御し、統一されたデリゲートモデルを提供します。
1つのセッションに複数のタスクを追加できます(通常は追加する必要があります)が、簡単に
するために、残りの手順は、単一のタスクの観点からライフサイクルについて説明します。
Important: デリゲートを指定せずにNSURLSessionクラスを使用する場合は、
completionHandlerパラメータを取る呼び出しを使用してタスクを作成する必要があります。
そうしないと、クラスからデータを取得できないからです。
4.
ダウンロードタスクでは、サーバからの転送中に、ユーザがアプリケーションにダウンロードを
一時停止するように指定した場合は、cancelByProducingResumeData:メソッドを呼び出してタ
スクをキャンセルします。その後、返されたレジュームデータをdownloadTaskWithResumeData:
またはdownloadTaskWithResumeData:completionHandler:メソッドのいずれかに渡して、ダ
ウンロードを続行する新しいダウンロードタスクを作成します。
5.
タスクが完了したら、NSURLSessionオブジェクトはタスクの完了ハンドラを呼び出します。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
69
URLセッションのライフサイクル
カスタムデリゲートを使用したURLセッションのライフサイクル
注意: NSURLSessionは、エラーパラメータを介してサーバエラーをレポートしません。
エラーパラメータを介してアプリケーションが受信するエラーのみが、ホスト名を解決
できない、ホストに接続できないといったクライアント側エラーです。エラーコード
は、URL Loading System Error Codesに説明があります。
サーバ側エラーは、NSHTTPURLResponseオブジェクトのHTTP状態コードを介してレポー
トされます。詳細については、NSHTTPURLResponseおよびNSURLResponseクラスのマ
ニュアルを参照してください。
6.
セッションが不要になった場合は、そのセッションを無効にします。未処理のタスクをキャンセ
ルする場合はinvalidateAndCancel、オブジェクトを無効にする前に未処理のタスクを終了させ
る場合はfinishTasksAndInvalidateを呼び出します。
カスタムデリゲートを使用したURLセッションのライフサイク
ル
デリゲートを指定せずにNSURLSession APIを使用できることも少なくありません。ただし、バックグ
ラウンドのダウンロードおよびアップロードでNSURLSession APIを使用している場合、あるいは認証
またはキャッシングをデフォルト以外の方法でを処理する必要がある場合、セッションデリゲートプ
ロトコル、1つ以上のタスクデリゲートプロトコル、あるいはこれらのプロトコルの組み合わせに従
うデリゲートを指定する必要があります。このデリゲートは次のような多くの目的に役立ちます。
●
ダウンロードタスクで使用する場合、NSURLSessionオブジェクトは、デリゲートを使用して、
ダウンロードされたデータを取得できるファイルのURLをアプリケーションに指定します。
デリゲートは、バックグラウンドでのすべてのダウンロードおよびアップロードに必要です。こ
れらのデリゲートは、NSURLSessionDownloadDelegateプロトコルのデリゲートメソッドをすべ
て指定する必要があります。
●
●
デリゲートは、特定のチャレンジ認証を処理できます。
デリゲートは、ストリームベースのデータをリモートサーバにアップロードするために、ボディ
ストリームを提供します。
●
デリゲートは、HTTPリダイレクトに従うかどうかを決定できます。
●
NSURLSessionオブジェクトは、デリゲートを使用して、転送ごとの状態をアプリケーションに
示します。データタスクデリゲートは、リクエストをダウンロードに変換できる最初の呼び出し
と、リモートサーバから届いたデータを提供する後続の呼び出しの両方を受信します。
●
デリゲートは、転送が完了したときにそれをNSURLSessionオブジェクトがアプリケーションに
通知できる1つの方法です。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
70
URLセッションのライフサイクル
カスタムデリゲートを使用したURLセッションのライフサイクル
URLセッション(バックグラウンドタスクに必要)が指定されたカスタムデリゲートを使用している
場合は、URLの完全なライフサイクルがより複雑になります。NSURLSessionおよび独自に実装したデ
リゲートを利用する場合について、アプリケーションに実装するべき基本的なメソッド呼び出しと、
システム側から呼び出されるデリゲート呼び出しの流れを示します。
1.
セッション設定を作成します。フォアグラウンドセッションの場合、この設定には一意の識別子
を含める必要があります。その識別子を格納し、アプリケーションがクラッシュまたは終了ある
いは一時停止した場合はそれを使用してセッションと関連付け直します。
2.
セッションを作成し、設定オブジェクトと、必要に応じてデリゲートを指定します。
3.
セッション内でそれぞれがリソースリクエストを表すタスクオブジェクトを作成します。
各タスクは、一時停止状態から開始されます。アプリケーションは、タスクでresumeを呼び出し
た後、指定されたリソースのダウンロードを開始します。
タスクオブジェクトは、NSURLSessionTaskのサブクラスです。どのような動作にしたいかによっ
て、NSURLSessionDataTask、NSURLSessionUploadTask、NSURLSessionDownloadTaskのいず
れかを選択します。これらのオブジェクトはNSURLConnectionオブジェクトに似ていますが、よ
り詳細に制御し、統一されたデリゲートモデルを提供します。
1つのセッションに複数のタスクを追加できます(通常は追加する必要があります)が、簡単に
するために、残りの手順は、単一のタスクの観点からライフサイクルについて説明します。
4.
リモートサーバが認証が必要であることを示す状態コードを返す場合や、その認証で接続レベル
のチャレンジ(SSLクライアント証明書など)が必要な場合、NSURLSessionはチャレンジ認証デ
リゲートメソッドを呼び出します。
●
●
セッションレベルのチャレンジのNSURLAuthenticationMethodNTLM、
NSURLAuthenticationMethodNegotiate、
NSURLAuthenticationMethodClientCertificate、または
NSURLAuthenticationMethodServerTrustに対して、NSURLSessionオブジェクトはセッ
ションデリゲートのURLSession:didReceiveChallenge:completionHandler:メソッドを
呼び出します。アプリケーションがセッションデリゲートメソッドを提供しない場合、
NSURLSessionオブジェクトはタスクデリゲートの
URLSession:task:didReceiveChallenge:completionHandler:メソッドを呼び出してチャ
レンジを処理します。
セッションレベルのチャレンジ(他のすべて)に対して、NSURLSessionオブジェクトはセッ
ションデリゲートのURLSession:task:didReceiveChallenge:completionHandler:メソッ
ドを呼び出してチャレンジを処理します。アプリケーションがセッションデリゲートを提供
し、認証を処理する必要がある場合は、タスクレベルで認証を処理するか、セッションごと
にハンドラを明示的に呼び出すタスクレベルのハンドラを提供します。セッションデリゲー
トのURLSession:didReceiveChallenge:completionHandler:メソッドは、非セッション
レベルのチャレンジでは呼び出されません 。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
71
URLセッションのライフサイクル
カスタムデリゲートを使用したURLセッションのライフサイクル
注意: Kerberos認証は透過的に処理されます。
アップロードタスクで認証が失敗した場合、タスクのデータがストリームから提供される場合、
NSURLSessionオブジェクトはデリゲートのURLSession:task:needNewBodyStream:デリゲート
メソッドを呼び出します。その後、デリゲートは新しいNSInputStreamオブジェクトを提供し
て、新しいリクエストのボディデータを提供する必要があります。
NSURLSessionの認証デリゲートメソッドの書き込みの詳細については“チャレンジ認証とTLSチェー
ン認証” (55 ページ)を参照してください。
5.
HTTPリダイレクトレスポンスを受信すると、NSURLSessionオブジェクトはデリゲートの
URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:メソッド
を呼び出します。そのデリゲートメソッドは、提供されたNSURLRequestオブジェクト(リダイ
レクトに従う場合)、新しいNSURLRequestオブジェクト(別のURLにリダイレクトする場合)、
またはnil(リダイレクトのレスポンスボディを有効なレスポンスとして扱い、結果として返す
場合)のいずれかを使用して、提供された完了ハンドラを呼び出します。
●
●
6.
リダイレクトに従う場合は、ステップ4(チャレンジ認証の処理)に戻ります。
デリゲートがこのメソッドを実装していない場合、リダイレクトはリダイレクトの最大数ま
で続きます。
downloadTaskWithResumeData:またはdownloadTaskWithResumeData:completionHandler:に
よって作成された(再)ダウンロードタスクに対して、NSURLSessionは新しいタスクオブジェ
クトを使用してデリゲートの
URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:メソッドを呼び出しま
す。
7.
データタスクに対して、NSURLSessionオブジェクトはデリゲートの
URLSession:dataTask:didReceiveResponse:completionHandler:メソッドを呼び出します。
データタスクをダウンロードタスクに変換するかどうかを決定し、完了コールバックを呼び出し
てデータの受信またはデータのダウンロードを続行します。
アプリケーションがデータタスクをダウンロードタスクに変換することを選択した場合、
NSURLSessionが新しいダウンロードタスクをパラメータとして使用してデリゲートの
URLSession:dataTask:didBecomeDownloadTask:メソッドを呼び出します。この呼び出し以
降、デリゲートがデータタスクからコールバックを受信することはなくなり、ダウンロードタス
クからコールバックを受信し始めます。
8.
タスクがuploadTaskWithStreamedRequest:で作成された場合は、NSURLSessionがデリゲート
のURLSession:task:needNewBodyStream:メソッドを呼び出してボディデータを提供します。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
72
URLセッションのライフサイクル
カスタムデリゲートを使用したURLセッションのライフサイクル
9.
サーバのボディコンテンツの初回アップロード中(該当する場合)、デリゲートはアップロード
の進行状況をレポートする
URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:のコール
バックを定期的に受信します。
10. サーバからの転送中、タスクデリゲートは定期的にコールバックを受信して転送の進行状況をレ
ポートします。ダウンロードタスクでは、ディスクに正常に書き込まれたバイト数を使用して
セッションがデリゲートの
URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
メソッドを呼び出します。データタスクでは、受け取った実際のデータを使用してセッションが
デリゲートのURLSession:dataTask:didReceiveData:メソッドを呼び出します。
ダウンロードタスクでは、サーバからの転送中に、ユーザがアプリケーションにダウンロードを
一時停止するように指定した場合は、cancelByProducingResumeData:メソッドを呼び出してタ
スクをキャンセルします。
その後、ユーザがダウンロードを続行するよう指示した場合、アプリケーションは返されたレ
ジュームデータをdownloadTaskWithResumeData:または
downloadTaskWithResumeData:completionHandler:メソッドのいずれかに渡して、ダウンロー
ドを続行するためのタスクを改めて作成した後、手順3(タスクオブジェクトを作成し続行)に
進みます。
11. データタスクに対して、NSURLSessionオブジェクトはデリゲートの
URLSession:dataTask:willCacheResponse:completionHandler:メソッドを呼び出します。
その後、アプリケーションがキャッシュを可能にするかどうかを決定する必要があります。この
メソッドを実装していない場合は、デフォルトの挙動として、セッションの設定オブジェクトで
指定したキャッシュポリシーが使用されます。
12. ダウンロードタスクが正常終了した場合、NSURLSessionオブジェクトは一時 ファイルの場所を
渡して、タスクのURLSession:downloadTask:didFinishDownloadingToURL:メソッドを呼び出
します。アプリケーションは、このデリゲートメソッドが返される前に、このファイルからレス
ポンスデータを読み取るか、アプリケーションのサンドボックコンテナディレクトリ内の永続的
な場所にレスポンスデータを移動する必要があります。
13. タスクが完了すると、NSURLSessionオブジェクトは、エラーオブジェクト、または(タスクが
正常に完了している場合は)nilを使用して、デリゲートの
URLSession:task:didCompleteWithError:メソッドを呼び出します。
タスクが失敗した場合、多くのアプリケーションはリクエストを再試行するでしょう。ただし、
ユーザがダウンロードを取り消した場合、あるいは何度繰り返してもけっして成功しない旨のエ
ラーをサーバが返した場合は、再試行を取りやめます。とはいえ、即座に再試行してよいわけで
はありません。代わりに、サーバが到達可能かどうか判断するAPIを実行し、到達可能性が変化し
た旨の通知が届いた場合に限って、新たにリクエストを作成するようにしてください。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
73
URLセッションのライフサイクル
カスタムデリゲートを使用したURLセッションのライフサイクル
ダウンロードタスクを続行できる場合、NSErrorオブジェクトのuserInfo辞書には、
NSURLSessionDownloadTaskResumeDataキーに対する値が収容されます。アプリケーションは
この値を渡して、downloadTaskWithResumeData:または
downloadTaskWithResumeData:completionHandler:を呼び出し、これまでのダウンロード処
理を続行するタスクを新たに作成します。
タスクを続行できない場合は、改めてダウンロードタスクを作成し、最初からやり直してくださ
い。
いずれの場合も、サーバのエラー以外の原因で転送に失敗した場合は、手順3(タスクオブジェ
クトの作成と再開)に進みます。
注意: NSURLSessionは、エラーパラメータを介してサーバエラーをレポートしません。
エラーパラメータを介してデリゲートが受信するエラーのみが、ホスト名を解決できな
い、ホストに接続できないといったクライアント側エラーです。エラーコードは、URL
Loading System Error Codesに説明があります。
サーバ側エラーは、NSHTTPURLResponseオブジェクトのHTTP状態コードを介してレポー
トされます。詳細については、NSHTTPURLResponseおよびNSURLResponseクラスのマ
ニュアルを参照してください。
14. レスポンスがマルチパートエンコードされている場合、セッションはデリゲートの
didReceiveResponseメソッドを再び呼び出し、続いてゼロ回以上のdidReceiveDataの追加呼
び出しを行います。この場合は手順7(didReceiveResponse呼び出しの処理)に進みます。
15. セッションが不要になった場合は、そのセッションを無効にします。未処理のタスクをキャンセ
ルするにはinvalidateAndCancelを呼び出し、オブジェクトを無効にする前に未処理のタスクを
終了させるにはfinishTasksAndInvalidateを呼び出します。
セッションを無効にした後、未処理のタスクがキャンセルされたか終了していると、セッション
はデリゲートにURLSession:didBecomeInvalidWithError:メッセージを送信します。そのデリ
ゲートメソッドが返されると、セッションはデリゲートに対するその強参照を破棄します。
Important: セッションオブジェクトは、アプリケーションがセッションを明示的に無効にす
るまで、デリゲートに対する強参照を保持します。セッションを無効にしないと、アプリケー
ションはメモリをリークします。
アプリケーションが進行中のダウンロードをキャンセルすると、NSURLSessionオブジェクトはエラー
が発生したかのようにデリゲートのURLSession:task:didCompleteWithError:メソッドを呼び出し
ます。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
74
書類の改訂履歴
この表は「URLローディングシステムプログラミングガイド 」の改訂履歴です。
日付
メモ
2013-10-22
技術的に若干不明確であった箇所を修正しました。
2013-09-18
OS X v10.9およびiOS 7で新しいNSURLSession APIについて記述するた
めに更新しました。
2010-09-01
誤字を修正し、コード例の廃止予定の記号を削除しました。
2010-03-24
内容を改編し、新しい認証機能の説明を追加しました。
2009-08-14
「Cocoa Core Competencies」へのリンクを追加しました。
2008-05-20
iOSでのNSURLDownloadの利用可能性に関する内容を含めるために
更新しました。
2008-05-06
編集上の細かな変更を行いました。
2007-07-10
細かな誤字を訂正しました。
2006-05-23
サンプルコードへのリンクを追加しました。
2006-03-08
サンプルコードを更新しました。
2005-09-08
connectionDidFinishLoading:メソッドのシグネチャを修正しました。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
75
書類の改訂履歴
日付
メモ
2005-04-08
サンプルコードへのアクセス機構メソッドを追加しました。細かな
誤字を訂正しました。
2004-08-31
細かな誤字を訂正しました。
目次の順序を修正しました。
2003-07-03
トピック全体にわたってwillSendRequest:redirectResponse:
メソッドのシグネチャを修正しました。
2003-06-11
NSURLDownloadとNSURLConnectionの挙動の違いを概説する記事を
追加しました。
2003-06-06
インターネットからコンテンツをダウンロードするための、Safari
1.0を備えたMac OS X v10.2での新しいクラスの使用を取り上げた、
概念とタスクの図版の初回リリース。
2013-10-22 | Copyright © 2003, 2014 Apple Inc. All Rights Reserved.
76
Apple Inc.
Copyright © 2003, 2014 Apple Inc.
All rights reserved.
本書の一部あるいは全部を Apple Inc. から書
面による事前の許諾を得ることなく複写複製
(コピー)することを禁じます。また、製品
に付属のソフトウェアは同梱のソフトウェア
使用許諾契約書に記載の条件のもとでお使い
ください。書類を個人で使用する場合に限り
1 台のコンピュータに保管すること、またそ
の書類にアップルの著作権表示が含まれる限
り、個人的な利用を目的に書類を複製するこ
とを認めます。
Apple ロゴは、米国その他の国で登録された
Apple Inc. の商標です。
キーボードから入力可能な Apple ロゴについ
ても、これを Apple Inc. からの書面による事
前の許諾なしに商業的な目的で使用すると、
連邦および州の商標法および不正競争防止法
違反となる場合があります。
本書に記載されているテクノロジーに関して
は、明示または黙示を問わず、使用を許諾し
ません。 本書に記載されているテクノロジー
に関するすべての知的財産権は、Apple Inc.
が保有しています。 本書は、Apple ブランド
のコンピュータ用のアプリケーション開発に
使用を限定します。
本書には正確な情報を記載するように努めま
した。 ただし、誤植や制作上の誤記がないこ
とを保証するものではありません。
Apple Inc.
1 Infinite Loop
Cupertino, CA 95014
U.S.A.
Apple Japan
〒106-6140 東京都港区六本木 6
丁目10番1号 六本木ヒルズ
http://www.apple.com/jp
Offline copy. Trademarks go here.
Apple Inc. は本書の内容を確認しておりますが、本
書に関して、明示的であるか黙示的であるかを問わ
ず、その品質、正確さ、市場性、または特定の目的
に対する適合性に関して何らかの保証または表明を
行うものではありません。その結果、本書は「現状
有姿のまま」提供され、本書の品質または正確さに
関連して発生するすべての損害は、購入者であるお
客様が負うものとします。
いかなる場合も、Apple Inc. は、本書の内容に含ま
れる瑕疵または不正確さによって生じる直接的、間
接的、特殊的、偶発的、または結果的損害に対する
賠償請求には一切応じません。そのような損害の可
能性があらかじめ指摘されている場合においても同
様です。
上記の損害に対する保証および救済は、口頭や書面
によるか、または明示的や黙示的であるかを問わ
ず、唯一のものであり、その他一切の保証にかわる
ものです。 Apple Inc. の販売店、代理店、または従
業員には、この保証に関する規定に何らかの変更、
拡張、または追加を加える権限は与えられていませ
ん。
一部の国や地域では、黙示あるいは偶発的または結
果的損害に対する賠償の免責または制限が認められ
ていないため、上記の制限や免責がお客様に適用さ
れない場合があります。 この保証はお客様に特定
の法的権利を与え、地域によってはその他の権利が
お客様に与えられる場合もあります。