最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

ios wkwebview離線化加載h5資源解決方案

 更新時(shí)間:2018年04月23日 14:56:40   作者:melo的微博  
本篇文章主要介紹了ios wkwebview離線化加載h5資源解決方案,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

思路: 使用NSURLProtocol攔截請(qǐng)求轉(zhuǎn)發(fā)到本地。

1.確認(rèn)離線化需求

部門(mén)負(fù)責(zé)的app有一部分使用的線上h5頁(yè),長(zhǎng)期以來(lái)加載略慢...

于是考慮使用離線化加載。

確保[低速網(wǎng)絡(luò)]或[無(wú)網(wǎng)絡(luò)]可網(wǎng)頁(yè)秒開(kāi)。

2.使用[NSURLProtocol]攔截

區(qū)別于uiwebview wkwebview使用如下方法攔截

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  // 區(qū)別于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"];
  }
}
# 注冊(cè)NSURLProtocol攔截
- (IBAction)regist:(id)sender {
  [NSURLProtocol registerClass:[FilteredProtocol class]];
}
# 注銷(xiāo)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是下載后的臨時(shí)保存路徑,需要將它移動(dòng)到需要保存的位置
      [[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]真機(jī)不支持直接加載[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臨時(shí)文件夾
  [[NSFileManager defaultManager] copyItemAtURL:[NSURL fileURLWithPath:cacheFilePath] toURL:[NSURL fileURLWithPath:tmpFilePath] error:&saveError];
  NSLog(@"Migrate dist to tempory ok");
}

5.轉(zhuǎn)發(fā)請(qǐng)求

如果[/static]開(kāi)頭 => 則轉(zhuǎn)發(fā)[Request]到本地[.css/.js]資源

如果[index.html]結(jié)尾 => 就直接[Load]本地[index.html] (否則[index.html]可能會(huì)加載失敗)

//
// 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]結(jié)尾 => 就直接[Load]本地[index.html]
- (void)startLoading {
  NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
  // 標(biāo)示改request已經(jīng)處理過(guò)了,防止無(wú)限循環(huán)
  [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.拼接響應(yīng)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.響應(yīng)
    [[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 - 拼接響應(yīng)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

結(jié)語(yǔ):

完整[DEMO]請(qǐng)參考: https://github.com/meloalright/wk-proxy

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解iOS集成GoogleMap(定位、搜索)

    詳解iOS集成GoogleMap(定位、搜索)

    這篇文章主要介紹了iOS集成GoogleMap(定位、搜索)需要注意的地方,對(duì)此有興趣的讀者一起學(xué)習(xí)下吧。
    2018-02-02
  • iOS界面跳轉(zhuǎn)時(shí)導(dǎo)航欄和tabBar的隱藏與顯示功能

    iOS界面跳轉(zhuǎn)時(shí)導(dǎo)航欄和tabBar的隱藏與顯示功能

    這篇文章主要介紹了iOS界面跳轉(zhuǎn)時(shí)導(dǎo)航欄和tabBar的隱藏與顯示功能,需要的朋友可以參考下
    2017-02-02
  • iOS仿郵箱大師的九宮格手勢(shì)密碼解鎖

    iOS仿郵箱大師的九宮格手勢(shì)密碼解鎖

    這篇文章主要為大家詳細(xì)介紹了iOS仿郵箱大師的手勢(shì)密碼解鎖的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-04-04
  • iOS 防鍵盤(pán)遮擋的實(shí)例

    iOS 防鍵盤(pán)遮擋的實(shí)例

    下面小編就為大家分享一篇iOS 防鍵盤(pán)遮擋的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • iOS開(kāi)發(fā)之UITableView左滑刪除等自定義功能

    iOS開(kāi)發(fā)之UITableView左滑刪除等自定義功能

    今天來(lái)給大家介紹下iOS開(kāi)發(fā)中UITableView左滑實(shí)現(xiàn)微信中置頂,刪除等功能。對(duì)大家開(kāi)發(fā)iOS具有一定的參考借鑒價(jià)值,有需要的朋友們一起來(lái)看看吧。
    2016-09-09
  • iOS中關(guān)于模塊化開(kāi)發(fā)解決方案(純干貨)

    iOS中關(guān)于模塊化開(kāi)發(fā)解決方案(純干貨)

    這篇文章主要介紹了iOS中關(guān)于模塊化開(kāi)發(fā)解決方案(純干貨)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-09-09
  • iOS實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能

    iOS實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能

    這篇文章主要為大家詳細(xì)介紹了iOS實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • iOS App開(kāi)發(fā)中Masonry布局框架的基本用法解析

    iOS App開(kāi)發(fā)中Masonry布局框架的基本用法解析

    這篇文章主要介紹了iOS App開(kāi)發(fā)中Masonry布局框架的基本用法解析,Masonry支持iOS和OSX的Auto Layout,在GitHub上的人氣很高,需要的朋友可以參考下
    2016-03-03
  • iOS開(kāi)發(fā)定時(shí)器的三種方法分享

    iOS開(kāi)發(fā)定時(shí)器的三種方法分享

    相信在大家開(kāi)發(fā)過(guò)程中,常常需要在某個(gè)時(shí)間后執(zhí)行某個(gè)方法,或者是按照某個(gè)周期一直執(zhí)行某個(gè)方法。在這個(gè)時(shí)候,我們就需要用到定時(shí)器。然而,在iOS中有很多方法完成以上的任務(wù),到底有多少種方法呢?下面就通過(guò)這篇文章來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2016-09-09
  • iOS使用核心動(dòng)畫(huà)和粒子發(fā)射器實(shí)現(xiàn)點(diǎn)贊按鈕的方法

    iOS使用核心動(dòng)畫(huà)和粒子發(fā)射器實(shí)現(xiàn)點(diǎn)贊按鈕的方法

    這篇文章主要給大家介紹了iOS如何使用核心動(dòng)畫(huà)和粒子發(fā)射器實(shí)現(xiàn)點(diǎn)贊按鈕的方法,文中給出了詳細(xì)的示例代碼,相信對(duì)大家的理解和學(xué)習(xí)具有一定的參考借鑒,有需要的朋友們下面跟著小編一起來(lái)學(xué)習(xí)學(xué)習(xí)吧。
    2016-12-12

最新評(píng)論

巢湖市| 泽库县| 偏关县| 马关县| 五莲县| 延川县| 梨树县| 栾城县| 黔南| 航空| 阜新| 江华| 习水县| 沁源县| 三都| 全州县| 定西市| 手游| 绵竹市| 无棣县| 天柱县| 罗源县| 黔南| 平顶山市| 泰和县| 通化市| 松潘县| 长宁区| 桦川县| 加查县| 瑞金市| 都兰县| 卢氏县| 秀山| 英山县| 怀柔区| 石城县| 思茅市| 武强县| 商城县| 神池县|