【发布时间】:2013-07-27 08:07:41
【问题描述】:
我有一个简单的方法,它接受一个 url 并从服务器加载它:
- (void)loadURL:(NSString*)url
{
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] init];
request.HTTPMethod = @"GET";
request.URL = [NSURL URLWithString:url];
NSHTTPURLResponse* response;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
}
服务器返回一个 max-age 为 1 天的响应。
问题是当我重复运行这 3 行时,其中 2 行随机错过缓存并重新加载响应:
[self loadURL:@"http://192.168.0.105:8080/users/51bdbc73808897302f000001/avatar?size=200x200&access_token=abcdefghijklmnopqrstuvwxyzzp77eDLqub3EWfXGe4c09RoyipmXgcENwfE6EV9yzvgp5VTSZww"];
[self loadURL:@"http://192.168.0.105:8080/users/51ee9d4e263d08fe04000003/avatar?size=200x200&access_token=abcdefghijklmnopqrstuvwxyzzp77eDLqub3EWfXGe4c09RoyipmXgcENwfE6EV9yzvgp5VTSZww"];
[self loadURL:@"http://192.168.0.105:8080/users/51d17b81de38c60b20000006/avatar?size=200x200&access_token=abcdefghijklmnopqrstuvwxyzzp77eDLqub3EWfXGe4c09RoyipmXgcENwfE6EV9yzvgp5VTSZww"];
如果我在每个请求的查询字符串中添加一些随机的唯一数据(&x、&y、&z),它可以解决问题:
[self loadURL:@"http://192.168.0.105:8080/users/51bdbc73808897302f000001/avatar?size=200x200&access_token=abcdefghijklmnopqrstuvwxyzzp77eDLqub3EWfXGe4c09RoyipmXgcENwfE6EV9yzvgp5VTSZww&x"];
[self loadURL:@"http://192.168.0.105:8080/users/51ee9d4e263d08fe04000003/avatar?size=200x200&access_token=abcdefghijklmnopqrstuvwxyzzp77eDLqub3EWfXGe4c09RoyipmXgcENwfE6EV9yzvgp5VTSZww&y"];
[self loadURL:@"http://192.168.0.105:8080/users/51d17b81de38c60b20000006/avatar?size=200x200&access_token=abcdefghijklmnopqrstuvwxyzzp77eDLqub3EWfXGe4c09RoyipmXgcENwfE6EV9yzvgp5VTSZww&z"];
另外,如果我将查询字符串的长度减少到 80 个字符,它也可以解决问题:
[self loadURL:@"http://192.168.0.105:8080/users/51bdbc73808897302f000001/avatar?size=200x200&access_token=abcdefghijklmnopqrstuvwxyzzp77eDLqub3EWfXGe4c09Royipm"];
[self loadURL:@"http://192.168.0.105:8080/users/51ee9d4e263d08fe04000003/avatar?size=200x200&access_token=abcdefghijklmnopqrstuvwxyzzp77eDLqub3EWfXGe4c09Royipm"];
[self loadURL:@"http://192.168.0.105:8080/users/51d17b81de38c60b20000006/avatar?size=200x200&access_token=abcdefghijklmnopqrstuvwxyzzp77eDLqub3EWfXGe4c09Royipm"];
发生了什么事? 这是iOS中的错误吗?我该如何解决?
P.S:我在一个空的应用程序中测试了这个,在 iOS 5 和 6 上都没有额外的东西。
【问题讨论】:
-
如何验证URL加载系统是从缓存中读取还是访问远程服务器?请求中设置了哪些缓存控制标头?客户端是否使用缓存?请注意,缓存可能会忽略服务器指定的过期时间。
-
@CouchDeveloper 我运行 'tail -f server.log | grep avatar' 以在请求进入时实时查看请求。服务器将 Cache-Control 标头设置为 'max-age=86400' 的值。并且客户端设置了 NSURLCache。
-
您需要检查请求中的缓存控制标头。如前所述,客户端可以忽略从服务器或代理设置的到期日期。缓存相当复杂:13 Caching in HTTP
-
您可能还会在服务器日志中看到“缓存验证”,其状态代码通常为 304,没有实体主体。
-
@CouchDeveloper 请求中没有与缓存相关的标头。我知道缓存的复杂性,但我需要知道为什么 NSURLConnection 的行为会根据 url 发生变化。
标签: ios objective-c nsurlconnection nsurlrequest nsurlcache