為了對(duì)網(wǎng)頁(yè)中的圖片做緩存加快運(yùn)行速度涧衙,百度到這么一個(gè)抽象類
NSURLProtocol
可以監(jiān)聽所有請(qǐng)求日矫。
上代碼档痪,新建一個(gè)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文件需要頻繁調(diào)用一個(gè)函數(shù),可以用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
然后創(chuàng)建一個(gè)子類钦幔,繼承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請(qǐng)求的圖片
if (([str hasSuffix:@".png"] || [str hasSuffix:@".jpg"] || [str hasSuffix:@".gif"])
&& ![NSURLProtocol propertyForKey:hasInitKey inRequest:request]) {
//yes 表示子類能處理該請(qǐng)求
NSLog(@"===============yes yes yes yes ");
return YES;
}
}
return NO;
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
NSMutableURLRequest *mutableReqeust = [request mutableCopy];
//這邊可用干你想干的事情枕屉。。更改地址鲤氢,提取里面的請(qǐng)求內(nèi)容搀擂,或者設(shè)置里面的請(qǐng)求頭。卷玉。
return mutableReqeust;
}
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b{
return YES;
}
- (void)startLoading
{
NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
//做下標(biāo)記哨颂,防止遞歸調(diào)用
[NSURLProtocol setProperty:@YES forKey:hasInitKey inRequest:mutableReqeust];
//查看本地是否已經(jīng)緩存了圖片
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提供的緩存進(jìn)行保存圖片
[[SDImageCache sharedImageCache] storeImage:cacheImage
recalculateFromImage:NO
imageData:self.responseData
forKey:[[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL]
toDisk:YES];
[self.client URLProtocolDidFinishLoading:self];
}
@end
這樣只要在你加載網(wǎng)頁(yè)的時(shí)候啟動(dòng)或者關(guān)閉監(jiān)聽就好了。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//注冊(cè)這個(gè)方法相种,用于緩存網(wǎng)頁(yè)的圖片
[NSURLProtocol registerClass:[VCCustomURLProtocol class]];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[NSURLProtocol unregisterClass:[VCCustomURLProtocol class]];
}
這樣就可以實(shí)現(xiàn)了對(duì)網(wǎng)頁(yè)圖片的緩存威恼,大家可以盡情的試試了。