ioshtml5离线缓存⽂件,ioswkwebview离线化加载h5资源解决
⽅案
思路: 使⽤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: @"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, NSUserDomainMask, 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
#import
#import
static NSString*const matchingPrefix = @"10.2.138.225:3233/static/";
static NSString*const regPrefix = @"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 ([quest.URL.absoluteString hasSuffix:@"index.html"]) {
NSURL *url = quest.URL;
NSString *path = [FilteredProtocol generateDateReadPath: quest.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 {
}
}
- (void)stopLoading
{
if (tion != nil)
{
[tion cancel];
}
}
- (NSString *)getMIMETypeWithCAPIAtFilePath:(NSString *)path