NSURLCache - 参数不起作用的GET请求的磁盘缓存 [英] NSURLCache - Disk caching for GET request with parameters not working

查看:176
本文介绍了NSURLCache - 参数不起作用的GET请求的磁盘缓存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用NSURLCache将一些HTTP请求缓存到磁盘。在使用AFNetworking进行一些测试并且无法工作之后,我使用NSURLRequest创建了一个简单的示例。



我像这样初始化AppDelegate上的缓存,将内存大小设置为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 ?/城市/ API /城市/ 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:响应数据:data userInfo:nil storagePolicy:NSURLCacheStorageAllowed];
[urlCache storeCachedResponse:cachedResponse forRequest:request];

我的请求有HTTP Header Cache-Control,如:



response ['cache-control'] ='max-age = 36000,public'



我看到响应缓存在Cache.db文件中。



稍后,在下一次执行中或者在同一次执行中,我使用以下代码尝试从缓存中获取响应:

  NSCachedURLResponse * cachedResponse = [urlCache cachedResponseForRequest:request]; 
response = cachedResponse.response;
data = cachedResponse.data;

问题是,当请求上有GET参数时,cachedResponse始终为null 。如果请求是



我认真地认为这是一个在iOS 8.1中无法正常工作的问题


I'm trying to cache some HTTP requests to disk using NSURLCache. After doing some tests with AFNetworking and not working, I created a simple example using NSURLRequest.

I initialize the cache on the AppDelegate like this, setting the memory size to 0, forcing it to go always to Disk:

NSUInteger sz = 1024*1024*20;
NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:sz diskPath:nil];
[NSURLCache setSharedURLCache:cache];

I use the following code to store the response:

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

My request has the HTTP Header Cache-Control like:

response['cache-control'] = 'max-age=36000, public'

I see the response is cached in the file Cache.db.

And later, in the next execution or even in the same one, I use the following code to try to get the response from the Cache:

NSCachedURLResponse *cachedResponse = [urlCache cachedResponseForRequest:request];
response = cachedResponse.response;
data = cachedResponse.data;

The problem is that cachedResponse is always null when the request has GET parameters on it. If the request is "http://localhost:8000/cities/api/cities/", the result is stored and recovered later. But when it does have GET parameters, something is preventing the method [NSURLCache cachedResponseForRequest:request] from finding the request.

Giving this, I subclassed NSURLCache and implemented that method like this:

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

}

In this case under the GET request with parameters, it does follow every single line until getting the NSURLResponse that was cached before.

Any ideas on why is it not working normally when the request has GET parameters?

解决方案

Finally I overrided NSURLCache to be able to achieve what I was looking for:

  1. GET requests (with parameters) being cached to Disk
  2. Requests going to cache while "Cache-Control max-age" value says it is not expired, and going to the server again after expiration, storing the new response and starting the expiration time over
  3. If offline, always return the response (if it exists) from cache

NTURLCache - overrides NSURLCache

I seriously think this is an issue that is not working properly in iOS 8.1

这篇关于NSURLCache - 参数不起作用的GET请求的磁盘缓存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆