西海岸より

つらつらざつざつと

CookieをiPhone側でセット/削除する方法

Cookieは通常サーバ側で自動的にセットされるが、場合によってはiPhone側で制御したい場合もあり、その方法のメモ。

iPhoneは、アプリ単位で、共有クッキーストレージと呼ばれるものを持っており、iPhoneの通信APIはその共有クッキーストレージを参照しているらしい。
なので、クッキーをセットする手順としては、クッキーを作成してから、共有ストレージにセットすることになる。

//指定パラメータのクッキーをセット
//value: クッキーの値
//key: クッキーのキー名
//domain: クッキーを適用するドメイン(xxxx.ne.jp)
//path: クッキーの有効適用範囲(サーバ上のパス)
//expires: クッキーの有効期限(0は無限)
- (void)setCookie:(NSString *)value forKey:(NSString *)key domain:(NSString *)domain cookiePath:(NSString *)path expires:(NSString *)expires {
 
  //クッキーを作成
  NSDictionary *properties = [[NSMutableDictionary alloc] init];
  [properties setValue:[value stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
                forKey:NSHTTPCookieValue];
  [properties setValue:key forKey:NSHTTPCookieName];
  [properties setValue:domain forKey:NSHTTPCookieDomain];
  [properties setValue:expiress forKey:NSHTTPCookieExpires];
  [properties setValue:path forKey:NSHTTPCookiePath];
  NSHTTPCookie *cookie = [[NSHTTPCookie alloc] initWithProperties:properties];
  [properties release];
 
  //共通クッキーストレージを取得してセット
  NSHTTPCookieStorage *aStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
  [aStorage setCookie:cookie];
  [cookie release];
}

これで、NSURLConnectionやMPMoviePlayer、WebViewなどを用いた接続のクッキーに反映されます。

ちなみに削除は、以下の通り。(今回は特定のドメインのすべてのクッキーを削除するようにしている)

// 特定ドメインへのクッキーをクリアする
- (void)clearXXXXDomainCookie {
 
  //共通クッキーストレージを取得
  NSHTTPCookieStorage *aStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
  NSArray *cookies = [aStorage cookies];
 
  //特定のドメイン(xxxx.ne.jp)のクッキーを全て削除
  for (NSHTTPCookie *aCookie in cookies) {
    NSDictionary *prop = [aCookie properties];
    NSString *cookieDomain = [prop objectForKey:NSHTTPCookieDomain];
    if (cookieDomain && [cookieDomain isEqualToString:@"xxxx.ne.jp"]) {
  
      //無効なクッキーへ入れ替え。(deleteCookieのみだとキャッシュが残るため)
      //[prop setValue:@"" forKey:NSHTTPCookieValue];
      //追記:過去の時間を設定しクッキーを無効に
      [prop setValue:[NSDate dateWithTimeIntervalSinceNow:-3600]         forKey:NSHTTPCookieExpires];
      NSHTTPCookie *newCookie = [[NSHTTPCookie alloc] initWithProperties:prop];
      [aStorage deleteCookie:aCookie];
      [aStorage setCookie:newCookie];
      [newCookie release];
    }
  }
}

なぜだか、deleteCookieだけではキャッシュ(?)が残り、サーバ側には消したはずのクッキーの
明示的に空のクッキー値を入れるようにしています。

追記

コメントで頂いたように情報を教えていただきましたので追記しました。
otmbさん、grapeさんご指摘ありがとうございました。

deleteでクッキーが削除されない理由と思われる情報が以下に掲載されてます。

http://stackoverflow.com/questions/5070446/deleted-nshttpcookie-returns-if-app-is-terminated