最初から保存やら同期やらすべてを実装すると大変なので、まずはメモリ上だけでクッキーのやりとりを行う実装から始めよう。当面はラフな実装で動作確認を先行して行い、徐々に精度を高めていくやり方で進める。
今回はクッキーの受け取り処理を実装する。
(1) クライアント側の用意
まず WebView の WebResourceLoadDelegate として AppController を指定し、必要なデリゲートメソッドを実装する。
リクエスト処理では、setHTTPShouldHandleCookies を使い、デフォルトの NSHTTPCookieStorage の使用を中止する。
AppController.m
// WebResourceLoadDelegate
- (NSURLRequest *)webView:(WebView *)sender
resource:(id)identifier
willSendRequest:(NSURLRequest *)request
redirectResponse:(NSURLResponse *)redirectResponse
fromDataSource:(WebDataSource *)dataSource
{
[(NSMutableURLRequest*)request setHTTPShouldHandleCookies:NO];
return request;
}
続いてレスポンス処理では、受け取ったヘッダ情報を XCHTTPCookieStorageへ渡す。
- (void)webView:(WebView *)sender
resource:(id)identifier
didReceiveResponse:(NSURLResponse *)response
fromDataSource:(WebDataSource *)dataSource
{
NSDictionary* headers = [(NSHTTPURLResponse*)response allHeaderFields];
NSURL* URL = [response URL];
NSArray* cookies =
[NSHTTPCookie cookiesWithResponseHeaderFields:headers forURL:URL];
[[XCHTTPCookieStorage sharedHTTPCookieStorage] setCookies:cookies
forURL:URL
mainDocumentURL:URL];
}
(2) XCHTTPCookieStorage の実装
XCHTTPCookieStorage.m
初期化。
- (id)init
{
if (self = [super init]) {
_cookie_accept_policy = NSHTTPCookieAcceptPolicyAlways;
_cookies = [[NSMutableDictionary alloc] init];
}
return self;
}
インスタンス取得(シングルトン)。
+ (XCHTTPCookieStorage *)sharedHTTPCookieStorage
{
static XCHTTPCookieStorage* _cookie_storage = nil;
if (!_cookie_storage) {
_cookie_storage = [[XCHTTPCookieStorage alloc] init];
}
return _cookie_storage;
}
渡されたクッキーを内部処理する(保存する)。
- (void)setCookies:(NSArray *)cookies forURL:(NSURL *)URL mainDocumentURL:(NSURL *)mainDocumentURL
{
for (NSHTTPCookie *cookie in cookies) {
[self setCookie:cookie];
}
}
_keyForCookie: で生成される文字列をキーとして、NSMutableDictionaryへ格納する。
- (void)setCookie:(NSHTTPCookie *)cookie
{
[_cookies setValue:cookie forKey:[self _keyForCookie:cookie]];
}
_keyForCookie: はドメイン名、パス、名前を '/'区切りで連結したものを返す。この辺りは以前参考にした mySTEP の方法を借用した。
- (NSString*)_keyForCookie:(NSHTTPCookie*)cookie
{
return [NSString stringWithFormat:@"%@/%@/%@",
[cookie domain], [cookie path], [cookie name]];
}
実行時に NSDictionary に格納しているクッキーが見られるように「print cookies」ボタンを追加し、-[AppController printCookies:] へ接続する。
- (IBAction)printCookies:(id)sender
{
NSLog(@"%@", [[XCHTTPCookieStorage sharedHTTPCookieStorage] cookies]);
}
実行してみよう。
google.comを開く。
この時のクッキーは次の通り。既に1つ受け取っている。
ページの右上にある「ログイン」リンクを押す。
クッキーを見ると、1つ増えている。
サンプル:
CookieStorage-1.zip
- - - -
粗い実装だがまずは受け取りができるようなった。次はクッキー送出に取りかかってみる。