您好,登錄后才能下訂單哦!
這篇文章主要介紹ios中wkwebview離線化加載h5資源的示例分析,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
思路: 使用NSURLProtocol攔截請求轉發到本地。
1.確認離線化需求
部門負責的app有一部分使用的線上h6頁,長期以來加載略慢...
于是考慮使用離線化加載。
確保[低速網絡]或[無網絡]可網頁秒開。
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, 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 <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
以上是“ios中wkwebview離線化加載h5資源的示例分析”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。