为了对网页中的图片做缓存加快运行速度,百度到这么一个抽象类
NSURLProtocol
可以监听所有请求。
上代码,新建一个NSURLProtocol
的分类,
#import <Foundation/Foundation.h>
@interface NSURLProtocol (VCWebView)
+ (void)wk_registerScheme:(NSString*)scheme;
+ (void)wk_unregisterScheme:(NSString*)scheme;
@end
#import "NSURLProtocol+VCWebView.h"
#import <WebKit/WebKit.h>
//FOUNDATION_STATIC_INLINE 属于属于runtime范畴,你的.m文件需要频繁调用一个函数,可以用static inline来声明。从SDWebImage从get到的。
FOUNDATION_STATIC_INLINE Class ContextControllerClass() {
static Class cls;
if (!cls) {
cls = [[[WKWebView new] valueForKey:@"browsingContextController"] class];
}
return cls;
}
FOUNDATION_STATIC_INLINE SEL RegisterSchemeSelector() {
return NSSelectorFromString(@"registerSchemeForCustomProtocol:");
}
FOUNDATION_STATIC_INLINE SEL UnregisterSchemeSelector() {
return NSSelectorFromString(@"unregisterSchemeForCustomProtocol:");
}
@implementation NSURLProtocol (VCWebView)
+ (void)wk_registerScheme:(NSString *)scheme {
Class cls = ContextControllerClass();
SEL sel = RegisterSchemeSelector();
if ([(id)cls respondsToSelector:sel]) {
// 放弃编辑器警告
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[(id)cls performSelector:sel withObject:scheme];
#pragma clang diagnostic pop
}
}
+ (void)wk_unregisterScheme:(NSString *)scheme {
Class cls = ContextControllerClass();
SEL sel = UnregisterSchemeSelector();
if ([(id)cls respondsToSelector:sel]) {
// 放弃编辑器警告
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[(id)cls performSelector:sel withObject:scheme];
#pragma clang diagnostic pop
}
}
@end
然后创建一个子类,继承NSURLProtocol
#import "VCCustomURLProtocol.h"
#import "SDImageCache.h"
#import "NSData+ImageContentType.h"
#import "UIImage+MultiFormat.h"
static NSString * const hasInitKey = @"VCCustomURLProtocolKey";
@interface VCCustomURLProtocol ()
@property (nonatomic, strong)NSMutableData *responseData;
@property (nonatomic, strong)NSURLConnection *connection;
@end
@implementation VCCustomURLProtocol
+ (BOOL)canInitWithRequest:(NSURLRequest *)request{
if ([request.URL.scheme isEqualToString:@"http"]) {
NSString *str = request.URL.absoluteString;
NSString *str1 = request.URL.path;
NSLog(@"=================================%@",str);
NSLog(@"=================================%@",str1);
//只处理http请求的图片
if (([str hasSuffix:@".png"] || [str hasSuffix:@".jpg"] || [str hasSuffix:@".gif"])
&& ![NSURLProtocol propertyForKey:hasInitKey inRequest:request]) {
//yes 表示子类能处理该请求
NSLog(@"===============yes yes yes yes ");
return YES;
}
}
return NO;
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
NSMutableURLRequest *mutableReqeust = [request mutableCopy];
//这边可用干你想干的事情。。更改地址,提取里面的请求内容,或者设置里面的请求头。。
return mutableReqeust;
}
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b{
return YES;
}
- (void)startLoading
{
NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
//做下标记,防止递归调用
[NSURLProtocol setProperty:@YES forKey:hasInitKey inRequest:mutableReqeust];
//查看本地是否已经缓存了图片
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL];
NSData *data = [[SDImageCache sharedImageCache] diskImageDataBySearchingAllPathsForKey:key];
if (data) {
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:mutableReqeust.URL
MIMEType:[NSData sd_contentTypeForImageData:data]
expectedContentLength:data.length
textEncodingName:nil];
[self.client URLProtocol:self
didReceiveResponse:response
cacheStoragePolicy:NSURLCacheStorageNotAllowed];
[self.client URLProtocol:self didLoadData:data];
[self.client URLProtocolDidFinishLoading:self];
}
else {
self.connection = [NSURLConnection connectionWithRequest:mutableReqeust delegate:self];
}
}
- (void)stopLoading
{
[self.connection cancel];
}
#pragma mark- NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[self.client URLProtocol:self didFailWithError:error];
}
#pragma mark - NSURLConnectionDataDelegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
self.responseData = [[NSMutableData alloc] init];
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.responseData appendData:data];
[self.client URLProtocol:self didLoadData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
UIImage *cacheImage = [UIImage sd_imageWithData:self.responseData];
//利用SDWebImage提供的缓存进行保存图片
[[SDImageCache sharedImageCache] storeImage:cacheImage
recalculateFromImage:NO
imageData:self.responseData
forKey:[[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL]
toDisk:YES];
[self.client URLProtocolDidFinishLoading:self];
}
@end
这样只要在你加载网页的时候启动或者关闭监听就好了。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//注册这个方法,用于缓存网页的图片
[NSURLProtocol registerClass:[VCCustomURLProtocol class]];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[NSURLProtocol unregisterClass:[VCCustomURLProtocol class]];
}
这样就可以实现了对网页图片的缓存,大家可以尽情的试试了。