相信不少朋友用过UIWebView,webView下载的图片一般比较大,这个要能缓存就好了,可以大幅度提高加载速度,同时为用户节省流量。本文就是讲如何完美解决webView缓存的问题。
实际上,UIWebView自己是有缓存的,但容量有限,清理时间我们也不好掌握,那它是用什么做的缓存呢?是NSURLCache。看到它有几个方法:
+ (void)setSharedURLCache:(NSURLCache *)cache;
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request;
- (void)storeCachedResponse:(NSCachedURLResponse *)cachedResponse forRequest:(NSURLRequest *)request;
太好了,我们只要写一个子类继承NSURLCache,实现后两个方法,再让这个子类对象成为sharedURLCache,就可以操控webView的请求和缓存了。抛个砖吧:
上面的代码是专门用来搞定webView中的jpg图片的,其中MYURLCache提供了把data读、写入文件的功能,这个不是本文的重点,请各位自己实现吧。
在程序启动的时候,加入以下代码:
OK,搞定了,试试webView加载图片吧~
//=========================//
- (id)initWithMemoryCapacity:(NSUInteger)memoryCapacity diskCapacity:(NSUInteger)diskCapacity diskPath:(NSString *)path cacheTime:(NSInteger)cacheTime {
if (self = [self initWithMemoryCapacity:memoryCapacity diskCapacity:diskCapacity diskPath:path]) { self.cacheTime = cacheTime; if (path) self.diskPath = path; else self.diskPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; self.responseDictionary = [NSMutableDictionary dictionaryWithCapacity:0]; } return self;}- (void)dealloc { [_diskPath release]; [_responseDictionary release]; [super dealloc];}- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request { if ([request.HTTPMethod compare:@"GET"] != NSOrderedSame) { return [super cachedResponseForRequest:request]; } return [self dataFromRequest:request];}- (void)removeAllCachedResponses { [super removeAllCachedResponses]; [self deleteCacheFolder];}- (void)removeCachedResponseForRequest:(NSURLRequest *)request { [super removeCachedResponseForRequest:request]; NSString *url = request.URL.absoluteString; NSString *fileName = [self cacheRequestFileName:url]; NSString *otherInfoFileName = [self cacheRequestOtherInfoFileName:url]; NSString *filePath = [self cacheFilePath:fileName]; NSString *otherInfoPath = [self cacheFilePath:otherInfoFileName]; NSFileManager *fileManager = [NSFileManager defaultManager]; [fileManager removeItemAtPath:filePath error:nil]; [fileManager removeItemAtPath:otherInfoPath error:nil];}#pragma mark - custom url cache- (NSString *)cacheFolder { return @"URLCACHE";}- (void)deleteCacheFolder { NSString *path = [NSString stringWithFormat:@"%@/%@", self.diskPath, [self cacheFolder]]; NSFileManager *fileManager = [NSFileManager defaultManager]; [fileManager removeItemAtPath:path error:nil];}- (NSString *)cacheFilePath:(NSString *)file { NSString *path = [NSString stringWithFormat:@"%@/%@", self.diskPath, [self cacheFolder]]; NSFileManager *fileManager = [NSFileManager defaultManager]; BOOL isDir; if ([fileManager fileExistsAtPath:path isDirectory:&isDir] && isDir) { } else { [fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil]; } return [NSString stringWithFormat:@"%@/%@", path, file];}- (NSString *)cacheRequestFileName:(NSString *)requestUrl { return [Util md5Hash:requestUrl];}- (NSString *)cacheRequestOtherInfoFileName:(NSString *)requestUrl { return [Util md5Hash:[NSString stringWithFormat:@"%@-otherInfo", requestUrl]];}- (NSCachedURLResponse *)dataFromRequest:(NSURLRequest *)request { NSString *url = request.URL.absoluteString; NSString *fileName = [self cacheRequestFileName:url]; NSString *otherInfoFileName = [self cacheRequestOtherInfoFileName:url]; NSString *filePath = [self cacheFilePath:fileName]; NSString *otherInfoPath = [self cacheFilePath:otherInfoFileName]; NSDate *date = [NSDate date]; NSFileManager *fileManager = [NSFileManager defaultManager]; if ([fileManager fileExistsAtPath:filePath]) { BOOL expire = false; NSDictionary *otherInfo = [NSDictionary dictionaryWithContentsOfFile:otherInfoPath]; float u=[date timeIntervalSince1970]; NSLog(@"%f",u); if (self.cacheTime > 0) { NSInteger createTime = [[otherInfo objectForKey:@"time"] intValue]; if (createTime + self.cacheTime < [date timeIntervalSince1970]) { expire = true; } } if (expire == false) { NSLog(@"data from cache ..."); NSData *data = [NSData dataWithContentsOfFile:filePath]; NSURLResponse *response = [[NSURLResponse alloc] initWithURL:request.URL MIMEType:[otherInfo objectForKey:@"MIMEType"] expectedContentLength:data.length textEncodingName:[otherInfo objectForKey:@"textEncodingName"]]; NSCachedURLResponse *cachedResponse = [[[NSCachedURLResponse alloc] initWithResponse:response data:data] autorelease]; [response release]; return cachedResponse; } else { NSLog(@"cache expire ... "); [fileManager removeItemAtPath:filePath error:nil]; [fileManager removeItemAtPath:otherInfoPath error:nil]; } } //sendSynchronousRequest请求也要经过NSURLCache id boolExsite = [self.responseDictionary objectForKey:url]; if (boolExsite == nil) { [self.responseDictionary setValue:[NSNumber numberWithBool:TRUE] forKey:url]; NSError *error = nil; NSURLResponse *response = nil; NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; [self.responseDictionary removeObjectForKey:url]; if (error) { NSLog(@"error : %@", error); NSLog(@"not cached: %@", request.URL.absoluteString); return nil; } NSLog(@"get request ... "); //save to cache NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"%f", [date timeIntervalSince1970]], @"time", response.MIMEType, @"MIMEType", response.textEncodingName, @"textEncodingName", nil]; [dict writeToFile:otherInfoPath atomically:YES]; [data writeToFile:filePath atomically:YES]; NSCachedURLResponse *cachedResponse = [[[NSCachedURLResponse alloc] initWithResponse:response data:data] autorelease]; return cachedResponse; } return nil;}