应用程序退出时,NSHTTPCookieStorage状态未保存。是否有明确的知识/文档可供参考?

57

在这个问题上挣扎并且不愿意实现自定义cookie管理系统。

似乎iOS的HTTP实现中存在一些隐藏的问题,无法正确地处理无会话cookie。每当HTTP响应设置或删除cookie时,立即检查NSHTTPCookieStorage cookies将产生预期结果,并指示正确的sessionOnly值。

但是,如果应用程序在响应更新cookie后不久退出,在重新启动时,那些sessionOnly=FALSE cookie将恢复到某个先前状态,并且最近的更新将丢失。

无论是响应头还是NSHTTPCookieStorage setCookie:设置/删除cookie都没有区别。

幕后可能正在进行一些缓存/同步操作。使cookie变得持久需要的时间最长可以达到5秒。

是否有人能够提供关于此行为的明确解释?这是一个错误吗?还是我无法理解其目的的一些未记录功能?

您可以使用以下代码进行重现:

- (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];

}

这段代码应该在每次启动时输出新的值。但是,如果您快速退出应用程序,则会发现该值未更改。
一些可能相关的stack overflow问题: iphone NSHTTPCookieStorage可在应用程序重新打开时使用? iPhone:NSHTTPCookie在应用程序重新启动时不会保存 NSHTTPCookies拒绝被删除 如果应用程序终止,则删除的NSHTTPCookie会返回
3个回答

27
我认为答案在您的问题中链接到的其中一个SO帖子之一中:

我创建了一个样本项目来重现此问题——发现只有当应用程序收到SIGKILL信号时,例如在Xcode中停止调试器时才会发生。 在我的实验中,未处理的异常、崩溃、exit()和abort()不会导致NSHTPPCookieStorage失去数据。

由于这看起来是一个仅限于调试的问题(仅在使用调试器时才会发生),因此我关闭了先前提交的radar。

您可以通过正常重新启动手机并观察NSHTTPCookieStorage的所有更改是否正确持久化和重新加载来测试这一点。


谢谢更新。我还没有检查那里所做的调查,但听起来足够彻底。知道导致这种行为的有限条件应该足以避免这个陷阱。 - kball
这仍然适用于Xcode 6.4和模拟器版本8.4(SimulatorApp-565.9 CoreSimulator-117.15)。 - carbocation
2
这个问题仍然存在于Xcode 7.0.1和Simulator 9.1中。值得注意的是,如果应用程序在cookie值更改后很快被杀死,这也可能会发生在物理设备上。 - robnasby

16

我也遇到了相同的问题,但是我找到了一个解决方案。我保存浏览器创建的cookie,然后在应用程序重新启动时重新创建它们。

1)在UIWebView创建cookie时保存它们。

 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)现在当应用程序重新启动时,请重新创建它们:

- (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

}

谢谢


2
这应该是被接受的答案。Cookie 在应用程序退出时不会全局保存。此解决方案确保在应用程序被杀死和恢复时 Cookie 存在。谢谢。 - mkabatek

5
听起来需要进行类似于 NSUserDefaults 的“同步”调用。我认为你最好的选择是在标准的 NSUserDefaults 中单独管理应用程序的所有 cookie,并在启动时将任何缺失的 cookie 同步到 NSHTTPCookieStorage 中。或者,如果你感觉勇敢,可以查看是否存在一些私有的同步方法 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接