NSHTTPCookieStorage state not saved on app exit. Any definitive knowledge/documentation out there?
Struggling with this problem and loath to implement a custom cookie management system.
It appears some hidden level of iOS's implementation of HTTP fails to manage sessionless cookies properly. Any time an HTTP response sets or deletes a cookie, immediate inspection of NSHTTPCookieStorage cookies will yield the expected results and indicate the correct sessionOnly value.
But if the app quits soon after a response updates cookies, upon relaunch those sessionOnly=FALSE cookies will be reverted to some previous state and the most recent updates lost.
Whether the cookies are set/deleted by a response header or NSHTTPCookieStorage setCookie: makes no difference.
Some caching/syncing voodoo must be going on behind the scenes. The time it takes for the cookie to become persistent can be up to 5 seconds.
ANYONE out there who has or can point to some definitive explanation of this behavior? Is it a bug, plain and simple? Or some undocumented feature whose purpose I can't comprehend?
Some code you can use to reproduce:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
NSHTTPCookie *cookie;
for (cookie in [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies) {
NSLog(@"%@=%@", cookie.name, cookie.value);
}
NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
[cookieProperties setObject:@"testCookie" forKey:NSHTTPCookieName];
[cookieProperties setObject:[NSString stringWithFormat:@"%f", [[NSDate date] timeIntervalSince1970]] forKey:NSHTTPCookieValue];
[cookieProperties setObject:@"www.example.com" forKey:NSHTTPCookieDomain];
[cookieProperties setObject:@"www.example.com" forKey:NSHTTPCookieOriginURL];
[cookieProperties setObject:@"/" forKey:NSHTTPCookiePath];
[cookieProperties setObject:@"0" forKey:NSHTTPCookieVersion];
// set expiration to one month from now
[cookieProperties setObject:[[NSDate date] dateByAddingTimeInterval:2629743] forKey:NSHTTPCookieExpires];
cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}
This code should output a new value on every launch. Instead you will see that if you quit the app quickly the value is unchanged.
Some possibly related stack overflow questions:
iphone NSHTTPCookieStorage avaible on app reopen?
iPhone: NSHTTPCookie is not saved across app restarts
NSHTTPCookies refuse to be deleted
deleted NSHTTPCookie returns if app is terminated
I think the answer lies in one of the SO posts linked to in your question:
I made a sample project to reproduce this issue — and found that it would only occur when the app receives a SIGKILL signal, like when the debugger is stopped from within Xcode. In my experiments, unhandled exceptions, crashes, exit() and abort() don't cause NSHTPPCookieStorage to loose data.
As this looks like a debugging-only issue (it only occurs when using the debugger), I closed the radar I filled previously.
You can test this by restarting the phone normally and observing that all changes to NSHTTPCookieStorage are correctly persisted and reloaded.
I also got the same problem but i found a solution. I saved the cookies as it get created by the browser and then recreate them as app restarts.
1) Save cookie when they get created by uiwebview.
NSMutableArray *cookieArray = [[NSMutableArray alloc] init];
for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
[cookieArray addObject:cookie.name];
NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
[cookieProperties setObject:cookie.name forKey:NSHTTPCookieName];
[cookieProperties setObject:cookie.value forKey:NSHTTPCookieValue];
[cookieProperties setObject:cookie.domain forKey:NSHTTPCookieDomain];
[cookieProperties setObject:cookie.path forKey:NSHTTPCookiePath];
[cookieProperties setObject:[NSNumber numberWithInt:cookie.version] forKey:NSHTTPCookieVersion];
[cookieProperties setObject:[[NSDate date] dateByAddingTimeInterval:2629743] forKey:NSHTTPCookieExpires];
[[NSUserDefaults standardUserDefaults] setValue:cookieProperties forKey:cookie.name];
[[NSUserDefaults standardUserDefaults] synchronize];
}
[[NSUserDefaults standardUserDefaults] setValue:cookieArray forKey:@"cookieArray"];
[[NSUserDefaults standardUserDefaults] synchronize];
2) Now recreate them as app restarts:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSMutableArray* cookieDictionary = [[NSUserDefaults standardUserDefaults] valueForKey:@"cookieArray"];
NSLog(@"cookie dictionary found is %@",cookieDictionary);
for (int i=0; i < cookieDictionary.count; i++)
{
NSLog(@"cookie found is %@",[cookieDictionary objectAtIndex:i]);
NSMutableDictionary* cookieDictionary1 = [[NSUserDefaults standardUserDefaults] valueForKey:[cookieDictionary objectAtIndex:i]];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieDictionary1];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}
// other code
}
thanks