HTTP协议(三)之缓存

        当我们对容一个URL可能多次请求,并且请求返回的数据都是一样的,比如服务器上的图片,无论下载多少次都是一样的,这个时候我们就可以使用缓存,优点主要有两点:

1、避免用户浪费流量     2、提高程序的响应速度

        缓存分为内存缓存(沙盒缓存)和硬盘缓存。当我们第一次请求数据时,先检查内存缓存中有没有缓存数据,如果有就直接使用内存缓存中的数据,如果没有就检查硬盘缓存中有无缓存数据,如果有就使用,如果没有就向服务器请求数据。当服务器返回数据后,先使用返回的数据,然后将返回的数据缓存到硬盘中。此时再次请求这个数据就可以直接使用内存中的缓存了。

        在HTTP协议中,GET请求一般用来请求数据,而POST一般用来给服务器发送大量数据,所以我们一般对GET请求的数据进行缓存,不必对POST请求进行缓存。

        在iOS中,可以使用NSURLCache进行缓存。iOS中使用缓存策略来使用不同的缓存方案,提供了7种缓存策略:

  1. NSURLRequestUseProtocolCachePolicy:默认的缓存策略,取决于HTTP协议中是否需要缓存。

  2. NSURLRequestReloadIgnoringLocalCacheData:忽略缓存,重新请求。

  3. NSURLRequestReloadIgnoringLocalAndRemoteCacheData:未实现

  4. NSURLRequestReloadIgnoringCacheData:和第2种相同。

  5. NSURLRequestReturnCacheDataElseLoad:有缓存使用缓存,没有就重新请求。

  6. NSURLRequestReturnCacheDontLoad:只使用缓存,不发送请求(用于离线模式)

  7. NSURLRequestReloadRevalidatingCacheData:未实现   

 

        我们在开发时一般使用NSURLRequestReturnCacheDataElseLoad缓存策略,当我们发送请求返回数据后,数据会再内存和沙盒中缓存,再次请求这个数据的时候会从内存或者沙盒中取出数据,不再向服务器发送请求。

- (IBAction)getData:(id)sender {
    
    //创建请求
    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/video?method=get&type=JSON"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    //设置缓存策略
    request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;
    
    //发送请求,获得数据
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
        NSLog(@"dict:%@", dict);
    }];
}

        NSURLCache是一个非常重要的单例,它管理应用的所有缓存和缓存的属性设置。

获取/设置缓存大小:

- (NSUInteger)memoryCapacity;

/*! 
    @method diskCapacity
    @abstract Returns the on-disk capacity of the receiver. 
    @result The on-disk capacity, measured in bytes, for the receiver. 
*/
- (NSUInteger)diskCapacity;

/*! 
    @method setMemoryCapacity:
    @abstract Sets the in-memory capacity of the receiver. 
    @discussion At the time this call is made, the in-memory cache will
    truncate its contents to the size given, if necessary.
    @param memoryCapacity the new in-memory capacity, measured in
    bytes, for the receiver.
*/
- (void)setMemoryCapacity:(NSUInteger)memoryCapacity;

/*! 
    @method setDiskCapacity:
    @abstract Sets the on-disk capacity of the receiver. 
    @discussion At the time this call is made, the on-disk cache will
    truncate its contents to the size given, if necessary.
    @param diskCapacity the new on-disk capacity, measured in
    bytes, for the receiver.
*/
- (void)setDiskCapacity:(NSUInteger)diskCapacity;

内存使用量:

 

/*! 
    @method currentMemoryUsage
    @abstract Returns the current amount of space consumed by the
    in-memory cache of the receiver.
    @discussion This size, measured in bytes, indicates the current
    usage of the in-memory cache. 
    @result the current usage of the in-memory cache of the receiver.
*/
- (NSUInteger)currentMemoryUsage;

/*! 
    @method currentDiskUsage
    @abstract Returns the current amount of space consumed by the
    on-disk cache of the receiver.
    @discussion This size, measured in bytes, indicates the current
    usage of the on-disk cache. 
    @result the current usage of the on-disk cache of the receiver.
*/
- (NSUInteger)currentDiskUsage;

清除缓存:

 

/*! 
    @method removeCachedResponseForRequest:
    @abstract Removes the NSCachedURLResponse from the cache that is
    stored using the given request. 
    @discussion No action is taken if there is no NSCachedURLResponse
    stored with the given request.
    @param request the NSURLRequest to use as a key for the lookup.
*/
- (void)removeCachedResponseForRequest:(NSURLRequest *)request;

/*! 
    @method removeAllCachedResponses
    @abstract Clears the given cache, removing all NSCachedURLResponse
    objects that it stores.
*/
- (void)removeAllCachedResponses;

获取/保存某个请求的缓存:

 

/*! 
    @method cachedResponseForRequest:
    @abstract Returns the NSCachedURLResponse stored in the cache with
    the given request.
    @discussion The method returns nil if there is no
    NSCachedURLResponse stored using the given request.
    @param request the NSURLRequest to use as a key for the lookup.
    @result The NSCachedURLResponse stored in the cache with the given
    request, or nil if there is no NSCachedURLResponse stored with the
    given request.
*/
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request;

/*! 
    @method storeCachedResponse:forRequest:
    @abstract Stores the given NSCachedURLResponse in the cache using
    the given request.
    @param cachedResponse The cached response to store.
    @param request the NSURLRequest to use as a key for the storage.
*/
- (void)storeCachedResponse:(NSCachedURLResponse *)cachedResponse forRequest:(NSURLRequest *)request;

我们可以用下面这个方法手动获取某个请求:

 

- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request;

NSCachedURLResponse就是一个请求对应的缓存对象,从这个缓存对象中可以获取对应的缓存数据:

 

/*! 
    @method data
    @abstract Returns the data of the receiver. 
    @result The data of the receiver. 
*/
- (NSData *)data;

下面是一个获取天气信息的demo,使用NSURLRequestReturnCacheDataElseLoad缓存策略:

 

- (IBAction)getData:(id)sender {
    
    //创建请求
    NSURL *url = [NSURL URLWithString:@"http://www.weather.com.cn/adat/cityinfo/101010100.html"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    //设置缓存策略
    request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;
    
    //获取缓存数据
    NSURLCache *cache = [NSURLCache sharedURLCache];
    NSCachedURLResponse *cachedResponse = [cache cachedResponseForRequest:request];
    if (cachedResponse) {
        NSData *data = cachedResponse.data;
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
        NSLog(@"有缓存数据:%@", dict);
    }else {
        NSLog(@"没有缓存数据");
    }
    
    //发送请求,获得数据
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
        NSLog(@"dict:%@", dict);
    }];
}

第一次请求的输出:

 

2015-07-10 09:56:59.249 CacheDemo[21401:607] 没有缓存数据
2015-07-10 09:56:59.438 CacheDemo[21401:607] dict:{
    weatherinfo =     {
        city = "U5317U4eac";
        cityid = 101010100;
        img1 = "d1.gif";
        img2 = "n1.gif";
        ptime = "08:00";
        temp1 = "15U2103";
        temp2 = "5U2103";
        weather = "U591aU4e91";
    };
}

再次请求的输出:

 

2015-07-10 09:57:34.057 CacheDemo[21423:607] 有缓存数据:{
    weatherinfo =     {
        city = "U5317U4eac";
        cityid = 101010100;
        img1 = "d1.gif";
        img2 = "n1.gif";
        ptime = "08:00";
        temp1 = "15U2103";
        temp2 = "5U2103";
        weather = "U591aU4e91";
    };
}
2015-07-10 09:57:34.063 CacheDemo[21423:607] dict:{
    weatherinfo =     {
        city = "U5317U4eac";
        cityid = 101010100;
        img1 = "d1.gif";
        img2 = "n1.gif";
        ptime = "08:00";
        temp1 = "15U2103";
        temp2 = "5U2103";
        weather = "U591aU4e91";
    };
}

OK,可以使用缓存数据了。如果缓存数据过期那就要清除缓存,下面是清除缓存的实例:

 

- (IBAction)clearCache:(id)sender {
    //清除所有缓存
    NSLog(@"清除所有缓存");
    [[NSURLCache sharedURLCache] removeAllCachedResponses];
}

清除缓存后再次发送请求的输出:

 

2015-07-10 10:03:17.266 CacheDemo[21547:607] 清除所有缓存
2015-07-10 10:03:18.659 CacheDemo[21547:607] 没有缓存数据
2015-07-10 10:03:19.765 CacheDemo[21547:607] dict:{
    weatherinfo =     {
        city = "U5317U4eac";
        cityid = 101010100;
        img1 = "d1.gif";
        img2 = "n1.gif";
        ptime = "08:00";
        temp1 = "15U2103";
        temp2 = "5U2103";
        weather = "U591aU4e91";
    };
}

下面这个流程图很好的展示了如何使用缓存:

 

 

最后是Demo的下载地址:CacheDemo

posted @ 2015-07-22 09:55  驴车手  阅读(321)  评论(0编辑  收藏  举报