WKWebView

WKWebView是苹果在iOS 8之后推出的框架WebKit中的浏览器控件, 其加载速度比UIWebView快了许多, 但内存占用率却下降很多, 也解决了加载网页时的内存泄露问题. 现在的项目大多数只需适配到iOS 8, 所以用WKWebView来替换项目中的UIWebView是很有必要的.

WKWebView的使用主要涉及下面几个类:

WKWebView

WKWebViewConfiguration

WKUserScript

WKUserContentController

WKWebsiteDataStore

以及两个代理:

WKNavigationDelegate

WKUIDelegate

1. WKWebView

1.1 常用属性

// 导航代理@property(nullable,nonatomic,weak)id navigationDelegate;// UI代理@property(nullable,nonatomic,weak)idUIDelegate;// 页面标题, 一般使用KVO动态获取@property(nullable,nonatomic,readonly,copy)NSString*title;// 页面加载进度, 一般使用KVO动态获取@property(nonatomic,readonly)doubleestimatedProgress;// 可返回的页面列表, 已打开过的网页, 有点类似于navigationController的viewControllers属性@property(nonatomic,readonly,strong)WKBackForwardList*backForwardList;// 页面url@property(nullable,nonatomic,readonly,copy)NSURL*URL;// 页面是否在加载中@property(nonatomic,readonly,getter=isLoading)BOOLloading;// 是否可返回@property(nonatomic,readonly)BOOLcanGoBack;// 是否可向前@property(nonatomic,readonly)BOOLcanGoForward;// WKWebView继承自UIView, 所以如果想设置scrollView的一些属性, 需要对此属性进行配置@property(nonatomic,readonly,strong)UIScrollView*scrollView;// 是否允许手势左滑返回上一级, 类似导航控制的左滑返回@property(nonatomic)BOOLallowsBackForwardNavigationGestures;//自定义UserAgent, 会覆盖默认的值 ,iOS 9之后有效@property(nullable,nonatomic,copy)NSString*customUserAgent

1.2 一些方法:

// 带配置信息的初始化方法// configuration 配置信息- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration*)configuration// 加载请求- (nullableWKNavigation*)loadRequest:(NSURLRequest*)request;// 加载HTML- (nullableWKNavigation*)loadHTMLString:(NSString*)string baseURL:(nullableNSURL*)baseURL;// 返回上一级- (nullableWKNavigation*)goBack;// 前进下一级, 需要曾经打开过, 才能前进- (nullableWKNavigation*)goForward;// 刷新页面- (nullableWKNavigation*)reload;// 根据缓存有效期来刷新页面- (nullableWKNavigation*)reloadFromOrigin;// 停止加载页面- (void)stopLoading;// 执行JavaScript代码- (void)evaluateJavaScript:(NSString*)javaScriptString completionHandler:(void(^ _Nullable)(_Nullableid,NSError* _Nullable error))completionHandler;

2. WKWebViewConfiguration

// 通过此属性来执行JavaScript代码来修改页面的行为@property(nonatomic,strong)WKUserContentController*userContentController;//***********下面属性一般不需要设置// 首选项设置,  //可设置最小字号, 是否允许执行js//是否通过js自动打开新的窗口@property(nonatomic,strong)WKPreferences*preferences;// 是否允许播放媒体文件@property(nonatomic)BOOLallowsAirPlayForMediaPlayback// 需要用户来操作才能播放的多媒体类型@property(nonatomic)WKAudiovisualMediaTypesmediaTypesRequiringUserActionForPlayback// 是使用h5的视频播放器在线播放, 还是使用原生播放器全屏播放@property(nonatomic)BOOLallowsInlineMediaPlayback;

3. WKUserContentController

WKUserContentController 是JavaScript与原生进行交互的桥梁, 主要使用的方法有:

// 注入JavaScript与原生交互协议// JS 端可通过 window.webkit.messageHandlers..postMessage() 发送消息- (void)addScriptMessageHandler:(id)scriptMessageHandler name:(NSString*)name;// 移除注入的协议, 在deinit方法中调用- (void)removeScriptMessageHandlerForName:(NSString*)name;// 通过WKUserScript注入需要执行的JavaScript代码- (void)addUserScript:(WKUserScript*)userScript;// 移除所有注入的JavaScript代码- (void)removeAllUserScripts;

使用WKUserContentController注入的交互协议, 需要遵循WKScriptMessageHandler协议, 在其协议方法中获取JavaScript端传递的事件和参数:

- (void)userContentController:(WKUserContentController*)userContentController didReceiveScriptMessage:(WKScriptMessage*)message;

WKScriptMessage包含了传递的协议名称及参数, 主要从下面的属性中获取:

// 协议名称, 即上面的add方法传递的name@property(nonatomic,readonly,copy)NSString*name;// 传递的参数@property(nonatomic,readonly,copy)idbody;

4. WKUserScript

WKUserScript用于往加载的页面中添加额外需要执行的JavaScript代码, 主要是一个初始化方法:

/*

source: 需要执行的JavaScript代码

injectionTime: 加入的位置, 是一个枚举

typedef NS_ENUM(NSInteger, WKUserScriptInjectionTime) {

    WKUserScriptInjectionTimeAtDocumentStart,

    WKUserScriptInjectionTimeAtDocumentEnd

} API_AVAILABLE(macosx(10.10), ios(8.0));

forMainFrameOnly: 是加入所有框架, 还是只加入主框架

*/- (instancetype)initWithSource:(NSString*)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly;

5. WKUIDelegate

这个代理方法, 主要是用来处理使用系统的弹框来替换JS中的一些弹框的,比如: 警告框, 选择框, 输入框, 主要使用的是下面三个代理方法:

/**

webView中弹出警告框时调用, 只能有一个按钮

@param webView webView

@param message 提示信息

@param frame 可用于区分哪个窗口调用的

@param completionHandler 警告框消失的时候调用, 回调给JS

*/- (void)webView:(WKWebView*)webView runJavaScriptAlertPanelWithMessage:(NSString*)message initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void(^)(void))completionHandler {UIAlertController*alert = [UIAlertControlleralertControllerWithTitle:@"警告"message:message preferredStyle:(UIAlertControllerStyleAlert)];UIAlertAction*ok = [UIAlertActionactionWithTitle:@"我知道了"style:(UIAlertActionStyleDefault) handler:^(UIAlertAction* _Nonnull action) {        completionHandler();    }];        [alert addAction:ok];    [selfpresentViewController:alert animated:YEScompletion:nil];}/** 对应js的confirm方法

webView中弹出选择框时调用, 两个按钮

@param webView webView description

@param message 提示信息

@param frame 可用于区分哪个窗口调用的

@param completionHandler 确认框消失的时候调用, 回调给JS, 参数为选择结果: YES or NO

*/- (void)webView:(WKWebView*)webView runJavaScriptConfirmPanelWithMessage:(NSString*)message initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void(^)(BOOLresult))completionHandler {UIAlertController*alert = [UIAlertControlleralertControllerWithTitle:@"请选择"message:message preferredStyle:(UIAlertControllerStyleAlert)];UIAlertAction*ok = [UIAlertActionactionWithTitle:@"同意"style:(UIAlertActionStyleDefault) handler:^(UIAlertAction* _Nonnull action) {        completionHandler(YES);    }];UIAlertAction*cancel = [UIAlertActionactionWithTitle:@"不同意"style:(UIAlertActionStyleCancel) handler:^(UIAlertAction* _Nonnull action) {        completionHandler(NO);    }];        [alert addAction:ok];    [alert addAction:cancel];    [selfpresentViewController:alert animated:YEScompletion:nil];}/** 对应js的prompt方法

webView中弹出输入框时调用, 两个按钮 和 一个输入框

@param webView webView description

@param prompt 提示信息

@param defaultText 默认提示文本

@param frame 可用于区分哪个窗口调用的

@param completionHandler 输入框消失的时候调用, 回调给JS, 参数为输入的内容

*/- (void)webView:(WKWebView*)webView runJavaScriptTextInputPanelWithPrompt:(NSString*)prompt defaultText:(nullableNSString*)defaultText initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void(^)(NSString* _Nullable result))completionHandler {UIAlertController*alert = [UIAlertControlleralertControllerWithTitle:@"请输入"message:prompt preferredStyle:(UIAlertControllerStyleAlert)];        [alert addTextFieldWithConfigurationHandler:^(UITextField* _Nonnull textField) {        textField.placeholder =@"请输入";    }];UIAlertAction*ok = [UIAlertActionactionWithTitle:@"确定"style:(UIAlertActionStyleDefault) handler:^(UIAlertAction* _Nonnull action) {UITextField*tf = [alert.textFields firstObject];                        completionHandler(tf.text);    }];UIAlertAction*cancel = [UIAlertActionactionWithTitle:@"取消"style:(UIAlertActionStyleCancel) handler:^(UIAlertAction* _Nonnull action) {                completionHandler(defaultText);    }];        [alert addAction:ok];    [alert addAction:cancel];    [selfpresentViewController:alert animated:YEScompletion:nil];}

6. WKNavigationDelegate

// 决定导航的动作,通常用于处理跨域的链接能否导航。// WebKit对跨域进行了安全检查限制,不允许跨域,因此我们要对不能跨域的链接单独处理。// 但是,对于Safari是允许跨域的,不用这么处理。// 这个是决定是否Request- (void)webView:(WKWebView*)webView decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction decisionHandler:(void(^)(WKNavigationActionPolicy))decisionHandler{//  在发送请求之前,决定是否跳转decisionHandler(WKNavigationActionPolicyAllow);  }// 是否接收响应- (void)webView:(WKWebView*)webView decidePolicyForNavigationResponse:(WKNavigationResponse*)navigationResponse decisionHandler:(void(^)(WKNavigationResponsePolicy))decisionHandler{// 在收到响应后,决定是否跳转和发送请求之前那个允许配套使用decisionHandler(WKNavigationResponsePolicyAllow);}//用于授权验证的API,与AFN、UIWebView的授权验证API是一样的- (void)webView:(WKWebView*)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge completionHandler:(void(^)(NSURLSessionAuthChallengeDispositiondisposition,NSURLCredential*__nullablecredential))completionHandler{        completionHandler(NSURLSessionAuthChallengePerformDefaultHandling,nil);}// main frame的导航开始请求时调用- (void)webView:(WKWebView*)webView didStartProvisionalNavigation:(null_unspecifiedWKNavigation*)navigation{  }// 当main frame接收到服务重定向时调用- (void)webView:(WKWebView*)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecifiedWKNavigation*)navigation{// 接收到服务器跳转请求之后调用}// 当main frame开始加载数据失败时,会回调- (void)webView:(WKWebView*)webView didFailProvisionalNavigation:(null_unspecifiedWKNavigation*)navigation withError:(NSError*)error {}// 当内容开始返回时调用- (void)webView:(WKWebView*)webView didCommitNavigation:(null_unspecifiedWKNavigation*)navigation{  }//当main frame导航完成时,会回调- (void)webView:(WKWebView*)webView didFinishNavigation:(null_unspecifiedWKNavigation*)navigation{// 页面加载完成之后调用}// 当main frame最后下载数据失败时,会回调- (void)webView:(WKWebView*)webView didFailNavigation:(null_unspecifiedWKNavigation*)navigation withError:(NSError*)error {}// 当web content处理完成时,会回调- (void)webViewWebContentProcessDidTerminate:(WKWebView*)webView {}

7. WKWebsiteDataStore

WKWebsiteDataStore提供了网站所能使用的数据类型,包括 cookies,硬盘缓存,内存缓存活在一些WebSQL的数据持久化和本地持久化。可通过 ** WKWebViewConfiguration类的属性 websiteDataStore 进行相关的设置。WKWebsiteDataStore** 相关的API也比较简单:

// 默认的data store+ (WKWebsiteDataStore*)defaultDataStore;// 如果为webView设置了这个data Store,则不会有数据缓存被写入文件// 当需要实现隐私浏览的时候,可使用这个+ (WKWebsiteDataStore*)nonPersistentDataStore;// 是否是可缓存数据的,只读@property(nonatomic,readonly,getter=isPersistent)BOOLpersistent;// 获取所有可使用的数据类型+ (NSSet *)allWebsiteDataTypes;// 查找指定类型的缓存数据// 回调的值是WKWebsiteDataRecord的集合- (void)fetchDataRecordsOfTypes:(NSSet *)dataTypes completionHandler:(void(^)(NSArray *))completionHandler;// 删除指定的纪录// 这里的参数是通过上面的方法查找到的WKWebsiteDataRecord实例获取的- (void)removeDataOfTypes:(NSSet *)dataTypes forDataRecords:(NSArray *)dataRecords completionHandler:(void(^)(void))completionHandler;// 删除某时间后修改的某类型的数据- (void)removeDataOfTypes:(NSSet *)websiteDataTypes modifiedSince:(NSDate*)date completionHandler:(void(^)(void))completionHandler;// 保存的HTTP cookies@property(nonatomic,readonly)WKHTTPCookieStore*httpCookieStore

dataTyle

// 硬盘缓存WKWebsiteDataTypeDiskCache,// HTML离线web应用程序缓存WKWebsiteDataTypeOfflineWebApplicationCache,// 内存缓存WKWebsiteDataTypeMemoryCache,// 本地缓存WKWebsiteDataTypeLocalStorage,// cookiesWKWebsiteDataTypeCookies,// HTML会话存储WKWebsiteDataTypeSessionStorage,//  IndexedDB 数据库WKWebsiteDataTypeIndexedDBDatabases,// WebSQL 数据库WKWebsiteDataTypeWebSQLDatabases

WKWebsiteDataRecord

// 展示名称, 通常是域名@property(nonatomic,readonly,copy)NSString*displayName;// 包含的数据类型@property(nonatomic,readonly,copy)NSSet *dataTypes;

简单应用

删除指定时间的所有类型数据

NSSet*websiteDataTypes = [WKWebsiteDataStoreallWebsiteDataTypes];NSDate*dateFrom = [NSDatedateWithTimeIntervalSince1970:0];    [[WKWebsiteDataStoredefaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{// DoneNSLog(@"释放");    }];

查找删除

WKWebsiteDataStore*dataStore = [WKWebsiteDataStoredefaultDataStore];    [dataStore fetchDataRecordsOfTypes:[WKWebsiteDataStoreallWebsiteDataTypes] completionHandler:^(NSArray * _Nonnull records) {for(WKWebsiteDataRecord*recordinrecords) {            [dataStore removeDataOfTypes:record.dataTypes forDataRecords:@[record] completionHandler:^{// done}];        }    }];

查找删除特定的内容

WKWebsiteDataStore*dataStore = [WKWebsiteDataStoredefaultDataStore];    [dataStore fetchDataRecordsOfTypes:[WKWebsiteDataStoreallWebsiteDataTypes] completionHandler:^(NSArray * _Nonnull records) {for(WKWebsiteDataRecord*recordinrecords) {if([record.displayName isEqualToString:@"baidu"]) {                [dataStore removeDataOfTypes:record.dataTypes forDataRecords:@[record] completionHandler:^{// done}];            }        }    }];

来自:流火绯瞳  链接:https://www.jianshu.com/p/833448c30d70

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,552评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,666评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,519评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,180评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,205评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,344评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,781评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,449评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,635评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,467评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,515评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,217评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,775评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,851评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,084评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,637评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,204评论 2 341

推荐阅读更多精彩内容