NSURLCache – 参数不工作的GET请求的磁盘caching
我试图使用NSURLCachecaching一些HTTP请求到磁盘。 在使用AFNetworking进行一些testing之后,我使用NSURLRequest创build了一个简单的示例。
我像这样初始化AppDelegate上的caching,将内存大小设置为0,强制它始终移到磁盘:
NSUInteger sz = 1024*1024*20; NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:sz diskPath:nil]; [NSURLCache setSharedURLCache:cache];
我使用下面的代码来存储响应:
NSURLCache * urlCache = [NSURLCache sharedURLCache];
NSString *urlString = @"http://localhost:8000/cities/api/cities/?lang=en"; NSHTTPURLResponse *response = nil; NSError *error = nil; NSURL *finalUrl = [NSURL URLWithString:urlString]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:finalUrl]; request.cachePolicy = NSURLRequestReturnCacheDataElseLoad; NSData *data = nil; data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; NSCachedURLResponse *cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:response data:data userInfo:nil storagePolicy:NSURLCacheStorageAllowed]; [urlCache storeCachedResponse:cachedResponse forRequest:request];
我的请求有HTTP头caching控制像:
响应['cache-control'] ='max-age = 36000,public'
我看到响应被caching在Cache.db文件中。
之后,在下一次执行中,甚至在同一次执行中,我使用以下代码尝试从caching中获取响应:
NSCachedURLResponse *cachedResponse = [urlCache cachedResponseForRequest:request]; response = cachedResponse.response; data = cachedResponse.data;
问题是, 当请求具有GET参数时 ,cachedResponse始终为空。 如果请求是“ http:// localhost:8000 / cities / api / cities / ”,则结果稍后存储和恢复。 但是,当它具有GET参数时,阻止[NSURLCache cachedResponseForRequest:request]方法find请求。
给了这个,我分类NSURLCache和实现这样的方法:
- (id)initWithMemoryCapacity:(NSUInteger)memoryCapacity diskCapacity:(NSUInteger)diskCapacity diskPath:(NSString *)path { self = [super initWithMemoryCapacity:memoryCapacity diskCapacity:diskCapacity diskPath:path]; if (self) { NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); NSString *dir = (NSString*)[docPaths objectAtIndex:0]; dir = [dir stringByAppendingString:@"/uk.co.airsource.TestURLCache/nsurlcache"]; NSString *path = [dir stringByAppendingFormat:@"/Cache.db"]; self.db = [[FMDatabase alloc] initWithPath:path]; [self.db open]; int o = 4; } return self;
}
- (NSCachedURLResponse *) cachedResponseForRequest:(NSURLRequest *)request { NSCachedURLResponse *cachedURLResponse = [super cachedResponseForRequest:request]; if (cachedURLResponse == nil && [request.HTTPMethod isEqualToString:@"GET"]) { //[db executeQuery:@"select * from test where a = ?", @"hi'", nil]; NSLog(@"%@", request.URL.absoluteString); FMResultSet *cfurl_cache_response = [self.db executeQuery:@"select * from cfurl_cache_response where request_key = ? limit 1", request.URL.absoluteString, nil]; if ([cfurl_cache_response next]) { id entry_ID = [cfurl_cache_response objectForColumnName:@"entry_ID"]; [cfurl_cache_response close]; if (entry_ID != [NSNull null]) { FMResultSet *cfurl_cache_blob_data = [self.db executeQuery:@"select * from cfurl_cache_blob_data where entry_ID = ? limit 1", entry_ID, nil]; if ([cfurl_cache_blob_data next]) { id response_object = [cfurl_cache_blob_data objectForColumnName:@"response_object"]; [cfurl_cache_blob_data close]; FMResultSet *cfurl_receiver_data = [self.db executeQuery:@"select * from cfurl_cache_receiver_data where entry_ID = ? limit 1", entry_ID, nil]; if ([cfurl_receiver_data next]) { id receiver_data = [cfurl_receiver_data objectForColumnName:@"receiver_data"]; [cfurl_receiver_data close]; if (response_object != [NSNull null] && receiver_data != [NSNull null] && response_object && receiver_data) { NSURLResponse *urlResponse = [[NSURLResponse alloc] initWithURL:request.URL MIMEType:[[request allHTTPHeaderFields] objectForKey:@"Accept"] expectedContentLength:[(NSData *)response_object length] textEncodingName:nil]; cachedURLResponse = [[NSCachedURLResponse alloc] initWithResponse:urlResponse data:receiver_data userInfo:nil storagePolicy:NSURLCacheStorageAllowed]; } } } } } } return cachedURLResponse;
}
在这种情况下,带有参数的GET请求下,它会跟随每一行,直到获得之前被caching的NSURLResponse。
任何想法,为什么请求有GET参数时,它不正常工作?
问题似乎是没有指定内存容量,如果您指定的内存容量如下,
在这里,我指定的内存容量是1 MB的大小
[[NSURLCache alloc] initWithMemoryCapacity:1*1024*1024 diskCapacity:sz diskPath:nil];
它会起作用,看起来好像内存容量是不pipe用的,容量有多小,但不能空着。 那么你将能够提取存储的caching如下,
NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request]; response = cachedResponse.response; data = cachedResponse.data;
最后,我重写了NSURLCache,以便能够实现我正在寻找的内容:
- GET请求(带参数)被caching到磁盘
- 当“Cache-Control max-age”值表明它没有过期,并在到期后再次进入服务器,存储新的响应并开始到期时间
- 如果处于脱机状态,则始终从caching中返回响应(如果存在)
NTURLCache – 覆盖NSURLCache
我认真地认为这是一个在iOS 8.1中无法正常工作的问题