实现方案是:在内存中保存多个webView对象。不销毁。
使用案例:
// 预加载多个网页
NSArray *urlArray = @[@"https://www.baidu.com"];
[[XMWebViewManager defalutManager] preloadWebViewWithUrlArray:urlArray];
/// 具体页面的使用方式:
WKWebView *webV = [[XMWebViewManager defalutManager] getWebView:@"https://www.baidu.com"];
[self.view addSubview:webV];
[webV reload]; // reload能保证刷新最新的状态
总结:
WKWebview 会开辟进程(不是线程)来处理任务;
WKWebview 开辟的进程如果在内存超过预算之后,使用 WKWebview 的当前 app 并不会被杀掉,最多就是 WKWebview 展示的页面变成空白页;
核心代码如下:
/// 网页管理器 - 预加载、网页秒开等逻辑
@interface XMWebViewManager : NSObject
+ (instancetype)defalutManager;
/// 批量预加载网页方法
- (void)preloadWebViewWithUrlArray:(NSArray *)urlArray;
/// 根据url获取webview
- (WKWebView *)getWebView:(NSString *)urlString;
@end
//
// XMWebViewManager.m
// XMUI_OC
//
// Created by zhangmingwei6 on 2023/5/19.
// NSURLRequestUseProtocolCachePolicy:默认策略,具体的缓存逻辑和协议的声明有关,如果协议没有声明,不需要每次重新验证cache。 如果请求协议头为no-cache,则表现为直接从后台请求数据
#import "XMWebViewManager.h"
@interface XMWebViewManager()<WKNavigationDelegate, WKUIDelegate>
/// 预加载的网页
@property (nonatomic, strong) NSMutableArray *preloadWebViewArray;
@end
@implementation XMWebViewManager
+ (instancetype)defalutManager {
static XMWebViewManager *webviewManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
webviewManager = [[XMWebViewManager alloc] init];
webviewManager.preloadWebViewArray = [NSMutableArray array];
});
return webviewManager;
}
/// 根据url获取webview
- (WKWebView *)getWebView:(NSString *)urlString {
WKWebView *webV = nil;
for (NSDictionary *dict in self.preloadWebViewArray) {
if ([dict[@"url"] isEqualToString:urlString]) {
webV = dict[@"webview"];
}
}
if (webV == nil) {
webV = [self preloadWebViewWithUrlString:urlString];
}
return webV;
}
/// 预加载网页
- (WKWebView *)preloadWebViewWithUrlString:(NSString *)urlString {
if (!urlString || urlString.length <= 0) {
return nil;
}
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
WKWebView *webV = [[WKWebView alloc] initWithFrame:CGRectMake(0, kNaviStatusBarH_XM, kScreenWidth_XM, kScreenHeight_XM - kNaviStatusBarH_XM) configuration:config];
webV.UIDelegate = self;
webV.navigationDelegate = self;
NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30];
[webV loadRequest:req];
[webV reload];
NSMutableDictionary *urlWebViewDict = [NSMutableDictionary dictionary];
[urlWebViewDict setValue:webV forKey:@"webview"];
[urlWebViewDict setValue:urlString forKey:@"url"];
[self addPreloadAction:urlWebViewDict];
return webV;
}
/// 批量预加载网页方法
- (void)preloadWebViewWithUrlArray:(NSArray *)urlArray {
for (NSString *urlString in urlArray) {
[self preloadWebViewWithUrlString:urlString];
}
}
/// 添加到预加载数组中
- (void)addPreloadAction:(NSDictionary *)dict {
BOOL isExistFlag = NO;
for (int i = 0; i < self.preloadWebViewArray.count; i++) {
NSDictionary *urlwebDict = self.preloadWebViewArray[i];
if ([urlwebDict[@"url"] isEqualToString:dict[@"url"]]) {
isExistFlag = YES;
[self.preloadWebViewArray replaceObjectAtIndex:i withObject:dict];
}
}
if (!isExistFlag) {
// 最多添加10个缓存的webview
if (self.preloadWebViewArray.count < 10) {
[self.preloadWebViewArray addObject:dict];
} else {
[self.preloadWebViewArray replaceObjectAtIndex:0 withObject:dict];
}
}
}
/// 清除上个页面的缓存 - 防止展示上个网页的内容
//- (void)clearAction:(WKWebView *)webV {
// [webV evaluateJavaScript:@"window.document.body.remove();" completionHandler:^(id _Nullable, NSError * _Nullable error) {
//
// }];
//}
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
// NSURLRequestReturnCacheDataElseLoad 优先从本地拿数据,但是如果没有本地cache,则请求源数据
}
@end