zoukankan      html  css  js  c++  java
  • [ios] UIWebView的离线缓存【转】

    相信不少朋友用过UIWebView,webView下载的图片一般比较大,这个要能缓存就好了,可以大幅度提高加载速度,同时为用户节省流量。本文就是讲如何完美解决webView缓存的问题。

    实际上,UIWebView自己是有缓存的,但容量有限,清理时间我们也不好掌握,那它是用什么做的缓存呢?是NSURLCache。看到它有几个方法:

    + (void)setSharedURLCache:(NSURLCache *)cache;

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

    - (void)storeCachedResponse:(NSCachedURLResponse *)cachedResponse forRequest:(NSURLRequest *)request;

    太好了,我们只要写一个子类继承NSURLCache,实现后两个方法,再让这个子类对象成为sharedURLCache,就可以操控webView的请求和缓存了。抛个砖吧:

     
    - (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request {
                                                                                                                                                                                                                              
        NSString *pathString = [[request URL] absoluteString];
                                                                                                                                                                                                                              
        if(![pathString hasSuffix:@".jpg"]) {
            return[super cachedResponseForRequest:request];
        }
                                                                                                                                                                                                                              
        if([[MYURLCache sharedCache] hasDataForURL:pathString]) {
            NSData *data = [[MYURLCache sharedCache] dataForURL:pathString];
            NSURLResponse *response = [[[NSURLResponse alloc] initWithURL:[request URL]
                                                                 MIMEType:@"image/jpg"
                                                    expectedContentLength:[data length]
                                                         textEncodingName:nil] autorelease];
            return[[[NSCachedURLResponse alloc] initWithResponse:response data:data] autorelease];        
        }
        return[super cachedResponseForRequest:request];
    }
                                                                                                                                                                                                                          
    - (void)storeCachedResponse:(NSCachedURLResponse *)cachedResponse forRequest:(NSURLRequest *)request {
        NSString *pathString = [[request URL] absoluteString];
        if(![pathString hasSuffix:@".jpg"]) {
            [super storeCachedResponse:cachedResponse forRequest:request];
            return;
        }
                                                                                                                                                                                                                              
        [[MYURLCache sharedCache] storeData:cachedResponse.data forURL:pathString];
    }

    上面的代码是专门用来搞定webView中的jpg图片的,其中MYURLCache提供了把data读、写入文件的功能,这个不是本文的重点,请各位自己实现吧。

    在程序启动的时候,加入以下代码:

    MYURLCache *cache = [[MYURLCache alloc] init];
    [NSURLCache setSharedURLCache:cache];

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

  • 相关阅读:
    解决Maven项目 Missing artifact jdk.tools:jdk.tools:1.7的错误
    Hive三种不同的数据导出的方式
    【万字总结】图解堆算法、链表、栈与队列(多图预警)
    精心收集的Hadoop学习资料(持续更新)
    [大牛翻译系列]Hadoop 翻译文章索引
    sql server代理服务无法启动(SQL Agent):OpenSQLServerInstanceRegKey:GetRegKeyAccessMask failed (reason: 2).
    【转】sql server迁移到mysql
    linux shell中的EOF
    yum源出问题,rpmdb: BDB0113 Thread/process 17276/140338032428864 failed: BDB1507 Thread died in Berkeley DB library
    linux网卡出现问题:Job for network.service failed because the control process exited with error code问题
  • 原文地址:https://www.cnblogs.com/jinjiantong/p/3037594.html
Copyright © 2011-2022 走看看