首页 > 代码库 > iOS UIWebview 缓存文件。

iOS UIWebview 缓存文件。

最初我以为:

testCache = [[NSURLCache alloc]initWithMemoryCapacity:1024*1024*12 diskCapacity:1024*1024*120 diskPath:@"Assitant.db"];    
[NSURLCache setSharedURLCache:testCache];

就能让webview自动的控制缓存,没想到图片还是每次都在重新加载。实在就想不通了,120M还存不下?不知道是不是我用法没对。

后来经过一番查阅之后,发现似乎要自己实现缓存的读写!于是写了一个,花了三天时间,开始总是发现似乎写入成功了,但再进入有没有了。经过3天才发现是被我自己删除了,里面的删除函数,每次程序启动都会进行删除,无语了。


网上的资料确实不少,五花八门,不是过时了,就是不靠谱(此文写与2014-11-08 22:13,iOS7)。

上代码,使用方法在最下面。

//
//  MyUrlCache.h
//  com.lcst.miniBrowser
//
//  Created by lein on 14-11-5.
//  Copyright (c) 2014年 lein. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface MyUrlCache : NSURLCache
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request;
- (void) storeCachedResponse:(NSCachedURLResponse *)cachedResponse forRequest:(NSURLRequest *)request;
- (void) initilize;
- (void) doRemoveAllCachedResponses;
@end


//
//  MyUrlCache.m
//  com.lcst.miniBrowser
//
//  Created by lein on 14-11-5.
//  Copyright (c) 2014年 lein. All rights reserved.
//

#import "MyUrlCache.h"
#import "Utils.h"
@implementation MyUrlCache
#define WILL_BE_CACHED_EXTS ".jpg.png.gif.bmp.ico"
#define DEBUGP
//#define WILL_BE_CACHED_EXTS ".html"
NSString * spath;
NSFileManager *fileManager;
NSString* dirName=@"httpCache";
NSInteger dirType = 0;
-(void) initilize{
    fileManager = [NSFileManager defaultManager];
    NSArray *paths = NSSearchPathForDirectoriesInDomains((dirType==0?NSDocumentDirectory:(dirType==1?NSLibraryDirectory:NSCachesDirectory)), NSUserDomainMask, YES);
    
    spath =[paths objectAtIndex:0];
    [fileManager changeCurrentDirectoryPath:spath];
    spath = [spath stringByAppendingPathComponent:dirName];
    [fileManager changeCurrentDirectoryPath:spath];
}
- (void)removeAllCachedResponses{
    //这里不能执行doRemoveAllCachedResponses,否则每次就会删除你写入的
}
- (void) doRemoveAllCachedResponses{
    if (spath!=nil) {
        [fileManager removeItemAtPath:spath error:nil];
    }
}
- (NSString *) getMineType:(NSURLRequest *)request{
    NSString *ext = [[request URL] absoluteString].pathExtension;
    if(ext!=nil){
        NSString* str;
        if([ext compare:@"htm"]||[ext compare:@"html"])
            str = @"text/html";
        else
            str = [NSString stringWithFormat:@"image/%@", ext];
        return str;
    }
    return @"";
}
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request {
    NSString* filename = [self getCachedFileName:request];
    if(spath!=nil && filename.length>0){
        filename = [spath stringByAppendingPathComponent:filename];
        if([fileManager fileExistsAtPath:filename]){
#ifdef DEBUGP
            NSLog(@"\n注意::::Cache used: %@", [[request URL] absoluteString]);
#endif
            NSData* data = [NSData dataWithContentsOfFile:filename];
            NSURLResponse *response = [[NSURLResponse alloc] initWithURL:request.URL MIMEType:[self getMineType:request] expectedContentLength:data.length textEncodingName:nil];
            NSCachedURLResponse* cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:response data:data];
            
            return cachedResponse;
        }
    }

    return nil;
    
}

- (void)storeCachedResponse:(NSCachedURLResponse *)cachedResponse forRequest:(NSURLRequest *)request {
    NSString* filename = [self getCachedFileName:request];
    if(spath!=nil && filename.length>0){
        if(![fileManager fileExistsAtPath:filename]){
            filename = [Utils writeFileToDirWithDirType:dirName dirType:dirType fileName:filename DATA:cachedResponse.data];
#ifdef DEBUGP
            NSLog(@"\n注意::::写入缓存文件=%@",filename );
#endif
        }
    }
#ifdef DEBUGP
    else
        NSLog(@"\n注意::::不缓存: %@", [[request URL] absoluteString]);
#endif
}


- (NSString*) getCachedFileName:(NSURLRequest *) request{
    NSString *ext = [[request URL] absoluteString].pathExtension;
    if(ext!=nil){
        if([@WILL_BE_CACHED_EXTS rangeOfString:ext.lowercaseString].length>0){
            return [NSString stringWithFormat:@"%@.%@", [Utils md5:[[request URL] absoluteString]], ext];
        }
    }
    return @"";
}
@end


//
//  Utils.h
//  com.lcst.miniBrowser
//
//  Created by lein on 14-8-4.
//  Copyright (c) 2014年 lein. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>

@interface Utils : NSObject
+(void) writeFile:(NSString *) filePath data:(NSString *) _data;
+(NSString *) readFile:(NSString *) filePath;
+(NSString *) md5:(NSString *)str;
+(NSString *) replaceStringBetween:(NSString *) startStr EndString:(NSString *) endString Str:(NSString *) str;
+(NSInteger)getTs;
+(NSData *)uncompressZippedData:(NSData *)compressedData;
+(NSString*) writeFileToDirWithDirType:(NSString*) dirname dirType:(NSInteger) type fileName:(NSString*) filename DATA:(NSData *) data;
+(NSData*) readFileFromDirWithDirType:(NSString*) dirname dirType:(NSInteger) type fileName:(NSString*) filename;
@end

//
//  Utils.m
//  com.lcst.miniBrowser
//
//  Created by lein on 14-8-4.
//  Copyright (c) 2014年 lein. All rights reserved.
//

#import "Utils.h"
#import <zlib.h>

@implementation Utils
+(void) writeFile:(NSString *) filePath data:(NSString *) _data{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString* fileName = [[paths objectAtIndex:0] stringByAppendingPathComponent:filePath];
   
    
    // 用这个方法来判断当前的文件是否存在,如果不存在,就创建一个文件
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if ( ![fileManager fileExistsAtPath:fileName]) {
        NSLog(@"File %@ not exists!", fileName);
        [fileManager createFileAtPath:fileName contents:nil attributes:nil];
    }else NSLog(@"File %@ exists!", fileName);

     NSLog(@"File %@ will write!", fileName);
    [_data writeToFile:fileName atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
+(NSString *) replaceStringBetween:(NSString *) startStr EndString:(NSString *) endString Str:(NSString *) str{
    NSRange range1 = [str rangeOfString:startStr];
    int len = str.length - range1.location - range1.length;
    
    NSRange range2 = [str rangeOfString:endString options:NSCaseInsensitiveSearch range:NSMakeRange(range1.location+range1.length, len)];
    
    int start =range1.length+range1.location;
    len = range2.location-(range1.length+range1.location);
    NSString* toReplace = [str substringWithRange:NSMakeRange(start, len)];
    return [str stringByReplacingOccurrencesOfString:toReplace withString:@""];
}

+(NSString *) readFile:(NSString *) filePath{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString* fileName = [[paths objectAtIndex:0]stringByAppendingPathComponent:filePath];
    NSLog(@"File %@ will be read!", fileName);

    NSString* myString = [NSString stringWithContentsOfFile:fileName usedEncoding:NULL error:NULL];
    return myString;
}

//md5 32位 加密 (小写)
+ (NSString *)md5:(NSString *)srcString {
    const char *cStr = [srcString UTF8String ];
    
    unsigned char digest[ CC_MD5_DIGEST_LENGTH ];
    
    CC_MD5 ( cStr, (CC_LONG) strlen (cStr), digest );
    
    NSMutableString *result = [ NSMutableString stringWithCapacity : CC_MD5_DIGEST_LENGTH * 2 ];
    
    for ( int i = 0 ; i < CC_MD5_DIGEST_LENGTH ; i++)
        
        [result appendFormat : @"%02x" , digest[i]];
    
    return result;
}

+ (NSInteger)getTs{
    NSDate *date = [NSDate date];
    NSTimeInterval timestamp = [date timeIntervalSince1970];
        
    return (NSInteger) timestamp;
}
+(NSData *)uncompressZippedData:(NSData *)compressedData{
    if ([compressedData length] == 0) return compressedData;
    unsigned full_length = [compressedData length];
    unsigned half_length = [compressedData length] / 2;
    NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
    BOOL done = NO;
    int status;
    z_stream strm;
    strm.next_in = (Bytef *)[compressedData bytes];
    strm.avail_in = [compressedData length];
    strm.total_out = 0;
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    if (inflateInit2(&strm, (15+32)) != Z_OK) return nil;
    while (!done) {
        // Make sure we have enough room and reset the lengths.
        if (strm.total_out >= [decompressed length]) {
            [decompressed increaseLengthBy: half_length];
        }
        strm.next_out = [decompressed mutableBytes] + strm.total_out;
        strm.avail_out = [decompressed length] - strm.total_out;
        // Inflate another chunk.
        status = inflate (&strm, Z_SYNC_FLUSH);
        if (status == Z_STREAM_END) {
            done = YES;
        } else if (status != Z_OK) {
            break;
        }
    }
    if (inflateEnd (&strm) != Z_OK) return nil;
    // Set real length.
    if (done) {
        [decompressed setLength: strm.total_out];
        return [NSData dataWithData: decompressed];
    } else {
        return nil;
    }
}

+(NSString*) writeFileToDirWithDirType:(NSString*) dirname dirType:(NSInteger) type fileName:(NSString*) filename DATA:(NSData *) data{
    NSFileManager* fileManager = [NSFileManager defaultManager];
    NSArray *paths = NSSearchPathForDirectoriesInDomains((type==0?NSDocumentDirectory:(type==1?NSLibraryDirectory:NSCachesDirectory)), NSUserDomainMask, YES);
    NSString* spath =[paths objectAtIndex:0];
    [fileManager changeCurrentDirectoryPath:spath];
    if(dirname.length>0){
        [fileManager createDirectoryAtPath:dirname withIntermediateDirectories:YES attributes:nil error:nil];
        spath = [NSString stringWithFormat:@"%@/%@/%@", spath, dirname, filename];
    }else
        spath = [NSString stringWithFormat:@"%@/%@", spath, filename];
    
    [fileManager createFileAtPath:spath contents:data attributes:nil];
    return spath;
}

+(NSData*) readFileFromDirWithDirType:(NSString*) dirname dirType:(NSInteger) type fileName:(NSString*) filename{
    NSArray *paths = NSSearchPathForDirectoriesInDomains((type==0?NSDocumentDirectory:(type==1?NSLibraryDirectory:NSCachesDirectory)), NSUserDomainMask, YES);
    NSString* spath =[paths objectAtIndex:0];
    
    if(dirname.length>0)
        spath = [NSString stringWithFormat:@"%@/%@/%@", spath, dirname, filename];
    else
        spath = [NSString stringWithFormat:@"%@/%@", spath, filename];
    
    return [[NSData alloc] initWithContentsOfFile:spath];
}
@end

使用,在viewDidAppear:

testCache = [[MyUrlCache alloc]initWithMemoryCapacity:1024*1024*12 diskCapacity:1024*1024*120 diskPath:@"jiayuanAssitant.db"];
    [testCache initilize];
    
    [NSURLCache setSharedURLCache:testCache];

顺便提一下,iOS模拟器的硬盘位置在:/Users/mac用户名/Library/Application Support/iPhone Simulator;因为一直在真机上弄,连文件夹建立起没有都不知道,以至于纠结了三天,在模拟器上一看,才找到原因。




iOS UIWebview 缓存文件。