
思路: 使用NSURLProtocol拦截请求转发到本地。
1.确认离线化需求
部门负责的app有一部分使用的线上h5页,长期以来加载略慢...
于是考虑使用离线化加载。
确保[低速网络]或[无网络]可网页秒开。
2.使用[NSURLProtocol]拦截
区别于uiwebvIEw wkwebvIEw使用如下方法拦截
@interface VIEwController ()@end@implementation VIEwController- (voID)vIEwDIDLoad { [super vIEwDIDLoad]; // 区别于uiwebvIEw wkwebvIEw使用如下方法拦截 Class cls = NSClassFromString(@"WKbrowsingContextController"); SEL sel = NSSelectorFromString(@"registerSchemeForCustomProtocol:"); if ([(ID)cls respondsToSelector:sel]) { [(ID)cls performSelector:sel withObject:@"http"]; [(ID)cls performSelector:sel withObject:@"https"]; }}# 注册NSURLProtocol拦截- (IBAction)regist:(ID)sender { [NSURLProtocol registerClass:[FilteredProtocol class]];}# 注销NSURLProtocol拦截- (IBAction)unregist:(ID)sender { [NSURLProtocol unregisterClass:[FilteredProtocol class]];}3.下载[zip] + 使用[SSZipArchive]解压
需要先 #import "SSZipArchive.h
- (voID)downloadZip { NSDictionary *_headers; NSURLSession *_session = [self sessionWithheaders:_headers]; NSURL *url = [NSURL URLWithString: @"http://10.2.138.225:3238/dist.zip"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; // 初始化cachepath Nsstring *cachePath = [NSSearchPathForDirectorIEsInDomains(NSCachesDirectory,NSUserDomainMask,YES) lastObject]; NSfileManager *fm = [NSfileManager defaultManager]; // 删除之前已有的文件 [fm removeItemAtPath:[cachePath stringByAppendingPathComponent:@"dist.zip"] error:nil]; NSURLSessionDownloadTask *downloadTask=[_session downloadTaskWithRequest:request completionHandler:^(NSURL *location,NSURLResponse *response,NSError *error) { if (!error) { NSError *saveError; NSURL *saveUrl = [NSURL fileURLWithPath: [cachePath stringByAppendingPathComponent:@"dist.zip"]]; // location是下载后的临时保存路径,需要将它移动到需要保存的位置 [[NSfileManager defaultManager] copyItemAtURL:location toURL:saveUrl error:&saveError]; if (!saveError) { NSLog(@"task ok"); if([SSZipArchive unzipfileAtPath: [cachePath stringByAppendingPathComponent:@"dist.zip"] toDestination:cachePath]) { NSLog(@"unzip ok");// 解压成功 } else { NSLog(@"unzip err");// 解压失败 } } else { NSLog(@"task err"); } } else { NSLog(@"error is :%@",error.localizedDescription); } }]; [downloadTask resume];}4.迁移资源至[Nstemporary]
[wkwebvIEw]真机不支持直接加载[NSCache]资源
需要先迁移资源至[Nstemporary]
- (voID)migratedistToTempory { NSfileManager *fm = [NSfileManager defaultManager]; Nsstring *cachefilePath = [[NSSearchPathForDirectorIEsInDomains(NSCachesDirectory,YES) lastObject] stringByAppendingPathComponent:@"dist"]; Nsstring *tmpfilePath = [NstemporaryDirectory() stringByAppendingPathComponent:@"dist"]; // 先删除tempory已有的dist资源 [fm removeItemAtPath:tmpfilePath error:nil]; NSError *saveError; // 从caches拷贝dist到tempory临时文件夹 [[NSfileManager defaultManager] copyItemAtURL:[NSURL fileURLWithPath:cachefilePath] toURL:[NSURL fileURLWithPath:tmpfilePath] error:&saveError]; NSLog(@"Migrate dist to tempory ok");}5.转发请求
如果[/static]开头 => 则转发[Request]到本地[.CSS/.Js]资源
如果[index.HTML]结尾 => 就直接[Load]本地[index.HTML] (否则[index.HTML]可能会加载失败)
//// ProtocolCustom.m// proxy-browser//// Created by melo的微博 on 2018/4/8.// copyright © 2018年 com. All rights reserved.//#import <objc/runtime.h>#import <Foundation/Foundation.h>#import <MobileCoreServices/MobileCoreServices.h>static Nsstring*const matchingPrefix = @"http://10.2.138.225:3233/static/";static Nsstring*const regPrefix = @"http://10.2.138.225:3233";static Nsstring*const FilteredKey = @"FilteredKey";@interface FilteredProtocol : NSURLProtocol@property (nonatomic,strong) NSMutableData *responseData;@property (nonatomic,strong) NSURLConnection *connection;@end@implementation FilteredProtocol+ (BOol)canInitWithRequest:(NSURLRequest *)request{ return [NSURLProtocol propertyForKey:FilteredKey inRequest:request]== nil;}+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request{ NSLog(@"Got it request.URL.absoluteString = %@",request.URL.absoluteString); NSMutableURLRequest *mutableReqeust = [request mutablecopy]; //截取重定向 if ([request.URL.absoluteString hasPrefix:matchingPrefix]) { NSURL* proxyURL = [NSURL URLWithString:[FilteredProtocol generateProxyPath: request.URL.absoluteString]]; NSLog(@"Proxy to = %@",proxyURL); mutableReqeust = [NSMutableURLRequest requestWithURL: proxyURL]; } return mutableReqeust;}+ (BOol)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b{ return [super requestIsCacheEquivalent:a toRequest:b];}# 如果[index.HTML]结尾 => 就直接[Load]本地[index.HTML]- (voID)startLoading { NSMutableURLRequest *mutableReqeust = [[self request] mutablecopy]; // 标示改request已经处理过了,防止无限循环 [NSURLProtocol setProperty:@YES forKey:FilteredKey inRequest:mutableReqeust]; if ([self.request.URL.absoluteString hasSuffix:@"index.HTML"]) { NSURL *url = self.request.URL; Nsstring *path = [FilteredProtocol generateDateReadpath: self.request.URL.absoluteString]; NSLog(@"Read data from path = %@",path); NSfileHandle *file = [NSfileHandle fileHandleForReadingAtPath:path]; NSData *data = [file readDataToEndOffile]; NSLog(@"Got data = %@",data); [file closefile]; //3.拼接响应Response NSInteger dataLength = data.length; Nsstring *mimeType = [self getMIMETypeWithCAPIAtfilePath:path]; Nsstring *httpVersion = @"http/1.1"; NShttpURLResponse *response = nil; if (dataLength > 0) { response = [self jointResponseWithData:data dataLength:dataLength mimeType:mimeType requestUrl:url statusCode:200 httpVersion:httpVersion]; } else { response = [self jointResponseWithData:[@"404" dataUsingEnCoding:NSUTF8StringEnCoding] dataLength:3 mimeType:mimeType requestUrl:url statusCode:404 httpVersion:httpVersion]; } //4.响应 [[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{ if (self.connection != nil) { [self.connection cancel]; self.connection = nil; }}- (Nsstring *)getMIMETypeWithCAPIAtfilePath:(Nsstring *)path{ if (![[[NSfileManager alloc] init] fileExistsAtPath:path]) { return nil; } CFStringRef UTI = UTTypeCreatePreferredIDentifIErForTag(kUTTagClassfilenameExtension,(__brIDge CFStringRef)[path pathExtension],NulL); CFStringRef MIMEType = UTTypecopyPreferredTagWithClass (UTI,kUTTagClassMIMEType); CFRelease(UTI); if (!MIMEType) { return @"application/octet-stream"; } return (__brIDge Nsstring *)(MIMEType);}#pragma mark - 拼接响应Response- (NShttpURLResponse *)jointResponseWithData:(NSData *)data dataLength:(NSInteger)dataLength mimeType:(Nsstring *)mimeType requestUrl:(NSURL *)requestUrl statusCode:(NSInteger)statusCode httpVersion:(Nsstring *)httpVersion{ NSDictionary *dict = @{@"Content-type":mimeType,@"Content-length":[Nsstring stringWithFormat:@"%ld",dataLength]}; NShttpURLResponse *response = [[NShttpURLResponse alloc] initWithURL:requestUrl statusCode:statusCode httpVersion:httpVersion headerFIElds:dict]; return response;}#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 { [self.clIEnt URLProtocolDIDFinishLoading:self];}+ (Nsstring *)generateProxyPath:(Nsstring *) absoluteURL { Nsstring *tmpfilePath = [NstemporaryDirectory() stringByAppendingPathComponent:@"dist"]; Nsstring *fileabsoluteURL = [@"file:/" stringByAppendingString:tmpfilePath]; return [absoluteURL stringByReplacingOccurrencesOfString:regPrefix withString:fileabsoluteURL];}+ (Nsstring *)generateDateReadpath:(Nsstring *) absoluteURL { Nsstring *fileDataReadURL = [NstemporaryDirectory() stringByAppendingPathComponent:@"dist"]; return [absoluteURL stringByReplacingOccurrencesOfString:regPrefix withString:fileDataReadURL];}@end结语:
完整[DEMO]请参考: https://github.com/meloalright/wk-proxy
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
您可能感兴趣的文章:WKWebVIEw、WebVIEw和Js的交互方式详解iOS WKWebVIEw无法处理URL Scheme和App Store链接的问题解决Js交互点击WKWebVIEw中的图片实现预览效果iOS11 WKWebVIEw问题汇总iOS11 WKWebVIEw 无法加载内容的解决方法iOS中WKWebVIEw白屏问题的分析与解决iOS11 WKWebVIEw内容过滤规则详解IOS中UIWebVIEw、WKWebVIEw之Js交互清除WKWebVIEw cookies的方法ios下OC与Js交互之WKWebVIEw 总结以上是内存溢出为你收集整理的ios wkwebview离线化加载h5资源解决方案全部内容,希望文章能够帮你解决ios wkwebview离线化加载h5资源解决方案所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)