概述
本篇文章將闡述,WebKit核新的類和協(xié)議宗苍、MessageHandler消息處理器钻弄、JS->OC佃却,OC->JS 交互流程、WKNavagationDelegate協(xié)議窘俺、WKUIDelegate協(xié)議等類或方法分析WebKit
內(nèi)核的原理及應(yīng)用說明饲帅。
重點注意
WebKit
的函數(shù)和方法只能在App
的主線程或者主隊列中調(diào)用。
WebKit核新的類和協(xié)議
WKWebView:網(wǎng)頁的渲染與展示瘤泪,通過WKWebViewConfiguration可以進行配置灶泵。
WKWebViewConfiguration:這個類專門用來配置WKWebView。
WKPreference:這個類用來進行M相關(guān)設(shè)置对途。
WKProcessPool:這個類用來配置進程池赦邻,與網(wǎng)頁視圖的資源共享有關(guān)。
WKUserContentController:這個類主要用來做native與JavaScript的交互管理实檀。
WKUserScript:用于進行JavaScript注入惶洲。
WKScriptMessageHandler:這個類專門用來處理JavaScript調(diào)用native的方法。
WKNavigationDelegate:網(wǎng)頁跳轉(zhuǎn)間的導(dǎo)航管理協(xié)議膳犹,這個協(xié)議可以監(jiān)聽網(wǎng)頁的活動恬吕。
WKNavigationAction:網(wǎng)頁某個活動的示例化對象。
WKUIDelegate:用于交互處理JavaScript中的一些彈出框镣奋。
WKBackForwardList:堆棧管理的網(wǎng)頁列表币呵。
WKBackForwardListItem:每個網(wǎng)頁節(jié)點對象怀愧。
使用WKWebViewConfiguration對WebView進行配置
WebbView初始化
初始化函數(shù)
- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration;
加載方式侨颈,建議使用蘋果推薦使用的函數(shù)
// 加載HTML文件,推薦使用
- (WKNavigation *)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL;
// 加載一個請求芯义,推薦使用
- (WKNavigation *)loadRequest:(NSURLRequest *)request;
// 加載本地文件哈垢,如Html文件等,不推薦使用
- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL API_AVAILABLE(macosx(10.11), ios(9.0));
// // 加載本地文件,如Html文件等,不推薦使用
- (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL API_AVAILABLE(macosx(10.11), ios(9.0));
WKWebViewConfiguration內(nèi)容配置
-
WKPerference
偏好設(shè)置
//進行偏好設(shè)置
WKPreferences * preference = [[WKPreferences alloc]init];
//最小字體大小 當(dāng)將javaScriptEnabled屬性設(shè)置為NO時扛拨,可以看到明顯的效果
preference.minimumFontSize = 0;
//設(shè)置是否支持javaScript 默認(rèn)是支持的
preference.javaScriptEnabled = YES;
//設(shè)置是否允許不經(jīng)過用戶交互由javaScript自動打開窗口
preference.javaScriptCanOpenWindowsAutomatically = YES;
config.preferences = preference;
-
WKUserContentController
:native
與JavaScript
的交互管理
WKUserContentController
最重要的對象方法就是addScriptMessageHandler:name:
耘分,我把這個功能簡稱為MessageHandler
(消息處理器)。- addScriptMessageHandler:name:
有兩個參數(shù),第一個參數(shù)是userContentController
的代理對象(通常是self
)求泰,第二個參數(shù)是JS里發(fā)送postMessage
的對象(相當(dāng)于一個native
與js
相互識別的一個標(biāo)識)央渣。使用MessageHandler
功能,就必須要實現(xiàn)WKScriptMessageHandler
協(xié)議渴频。
//設(shè)置內(nèi)容交互控制器 用于處理JavaScript與native交互
WKUserContentController * userController = [[WKUserContentController alloc]init];
//設(shè)置處理代理并且注冊要被js調(diào)用的方法名稱
[userController addScriptMessageHandler:self name:@"name"];
//js注入芽丹,注入一個測試方法。
NSString *javaScriptSource = @"function userFunc(){window.webkit.messageHandlers.name.postMessage( {\"name\":\"HS\"})}";
WKUserScript *userScript = [[WKUserScript alloc] initWithSource:javaScriptSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
// forMainFrameOnly:NO(全局窗口)卜朗,yes(只限主窗口)[userController addUserScript:userScript];
config.userContentController = userController;
- 在native代理的回調(diào)方法中拔第,會獲取到JavaScript傳遞進來的消息
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
//這里可以獲取到JavaScript傳遞進來的消息
}
-
WKScriptMessage
類是JavaScript
傳遞的對象實例
//傳遞的消息主體
@property (nonatomic, readonly, copy) id body;
//傳遞消息的WebView
@property (nullable, nonatomic, readonly, weak) WKWebView *webView;
//傳遞消息的WebView當(dāng)前頁面對象
@property (nonatomic, readonly, copy) WKFrameInfo *frameInfo;
//消息名稱,也就是我們注冊回調(diào)的“name”
@property (nonatomic, readonly, copy) NSString *name;
- 注入JS腳本
- (void)addUserScript:(WKUserScript *)userScript;
-
WKWebsiteDataStore
:WebKit
框架采用其本身的緩存框架
@interface WKWebsiteDataStore : NSObject
//獲取默認(rèn)的存儲器 此存儲器為持久性的會被寫入磁盤
+ (WKWebsiteDataStore *)defaultDataStore;
//獲取一個臨時的存儲器
+ (WKWebsiteDataStore *)nonPersistentDataStore;
//存儲器是否是臨時的
@property (nonatomic, readonly, getter=isPersistent) BOOL persistent;
//所有可以存儲的類型
+ (NSSet<NSString *> *)allWebsiteDataTypes;
@end
//設(shè)置數(shù)據(jù)存儲store
config.websiteDataStore = [WKWebsiteDataStore defaultDataStore];
//設(shè)置是否將網(wǎng)頁內(nèi)容全部加載到內(nèi)存后再渲染
config.suppressesIncrementalRendering = NO; //設(shè)置HTML5視頻是否允許網(wǎng)頁播放 設(shè)置為NO則會使用本地播放器
config.allowsInlineMediaPlayback = YES; //設(shè)置是否允許ariPlay播放
config.allowsAirPlayForMediaPlayback = YES; //設(shè)置視頻是否需要用戶手動播放 設(shè)置為NO則會允許自動播放
config.requiresUserActionForMediaPlayback = NO; //設(shè)置是否允許畫中畫技術(shù) 在特定設(shè)備上有效
config.allowsPictureInPictureMediaPlayback = YES; //設(shè)置選擇模式 是按字符選擇 還是按模塊選擇/*
typedef NS_ENUM(NSInteger, WKSelectionGranularity) {
//按模塊選擇
WKSelectionGranularityDynamic,
//按字符選擇
WKSelectionGranularityCharacter,
} NS_ENUM_AVAILABLE_IOS(8_0);
*/
config.selectionGranularity = WKSelectionGranularityCharacter; //設(shè)置請求的User-Agent信息中應(yīng)用程序名稱 iOS9后可用
config.applicationNameForUserAgent = @"HS";
JS->OC,OC->JS 交互流程
Native 實現(xiàn)方式
//防止頻繁IO操作场钉,造成性能影響
static NSString *nativejsSource;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
nativejsSource = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"NativeApi" ofType:@"js"] encoding:NSUTF8StringEncoding error:nil];
});
//添加自定義的腳本
WKUserScript *js = [[WKUserScript alloc] initWithSource:nativejsSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[self.webView.configuration.userContentController addUserScript:js];
//注冊分享回調(diào)
[self.webView.configuration.userContentController addScriptMessageHandler:self name:@"nativeShare"];
// 注冊添加聯(lián)系人的回調(diào)
[self.webView.configuration.userContentController addScriptMessageHandler:self name:@"nativeChoosePhoneContact"];
JS端實現(xiàn)方式
/**
* Native為H5提供的Api接口
*
* @type {js對象}
*/
var DANativeApi = (function() {
var NativeApi = {
/**
* 分享
* @param {js對象} shareInfo 分享信息和回調(diào)
* @return {void} 無同步返回值蚊俺,異步返回分享結(jié)果 true or false
*/
share: function(shareInfo) {
if (shareInfo == undefined || shareInfo == null || typeof(shareInfo) !== "object") {
alert("參數(shù)" + JSON.stringify(shareInfo) + "不合法");
} else {
alert("分享的參數(shù)為" + JSON.stringify(shareInfo));
}
//調(diào)用native端
_nativeShare(shareInfo);
},
/**
* 從通訊錄選擇聯(lián)系人
* @return {void} 無同步返回值,異步返回選擇的結(jié)果
*/
choosePhoneContact: function(param) {
//具體是否需要判斷
//調(diào)用native端
_nativeChoosePhoneContact(param);
}
}
//下面是一些私有函數(shù)
/**
* Native端實現(xiàn)逛万,適用于WKWebView泳猬,UIWebView如何實現(xiàn),小伙伴自己動腦筋吧~
* @param {js對象} shareInfo 分享的信息和回調(diào)
* @return {void} 無同步返回值宇植,異步返回
*/
function _nativeShare(shareInfo) {
//用于WKWebView暂殖,因為WKWebView并沒有辦法把js function傳遞過去,因此需要特殊處理一下
//把js function轉(zhuǎn)換為字符串当纱,oc端調(diào)用時 (<js function string>)(true); 即可
//如果有回調(diào)函數(shù)呛每,且為function
var callbackFunction = shareInfo.result;
if (callbackFunction != undefined && callbackFunction != null && typeof(callbackFunction) === "function") {
shareInfo.result = callbackFunction.toString();
}
//js -> oc
// 至于Android端,也可以坡氯,比如 window.jsInterface.nativeShare(JSON.stringify(shareInfo));
window.webkit.messageHandlers.nativeShare.postMessage(shareInfo);
}
/**
* Native端實現(xiàn)選擇聯(lián)系人晨横,并異步返回結(jié)果
* @param {[type]} param [description]
* @return {[type]} [description]
*/
function _nativeChoosePhoneContact(param) {
var callbackFunction = param.completion;
if (callbackFunction != undefined && callbackFunction != null && typeof(callbackFunction) === "function") {
param.completion = callbackFunction.toString();
}
//js -> oc
window.webkit.messageHandlers.nativeChoosePhoneContact.postMessage(param);
}
//閉包,把Api對象返回
return NativeApi;
})();
/*
//調(diào)用時箫柳,分享
DANativeApi.share({
title: document.title,
desc: "",
url: location.href,
imgUrl: "",
result: function(res) {
// body...
alert("分享結(jié)果為:" + JSON.stringify(res));
}
});
//選擇聯(lián)系人
DANativeApi.choosePhoneContact({
completion: function(res) {
alert("選擇聯(lián)系人的結(jié)果為:" + JSON.stringify(res));
}
});
*/
釋放回調(diào)
- (void)dealloc
{
// 注冊的回調(diào)要及時釋放手形,防止強引用,循環(huán)引用
[self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"nativeShare"];
[self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"nativeChoosePhoneContact"];
}
OC調(diào)用JS
// 將分享結(jié)果返回給js
NSString *jsStr = [NSString stringWithFormat:@"shareResult('%@','%@','%@')",title,content,url];
[self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"%@----%@",result, error);
}];
實現(xiàn)WKScriptMessageHandler協(xié)議方法(JS調(diào)用OC)
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
// 分享
if ( [message.name isEqualToString:@"nativeShare"]) {
// JS ->OC
// 第一步悯恍,處理分享數(shù)據(jù)
NSDictionary *shareData = message.body;
NSLog(@"%@分享的數(shù)據(jù)為: %@", message.name, shareData);
// 第二步库糠,彈出分享的圖層,執(zhí)行分享操作
// 第三部涮毫,模擬異步回調(diào)瞬欧,將分享狀態(tài)反饋給JS端
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//讀取js function的字符串
NSString *jsFunctionString = shareData[@"result"];
//拼接調(diào)用該方法的js字符串
NSString *callbackJs = [NSString stringWithFormat:@"(%@)(%d);", jsFunctionString, NO]; //后面的參數(shù)NO為模擬分享失敗
//執(zhí)行回調(diào)OC->JS,調(diào)用JS端的方法罢防,將分享狀態(tài)告知js,然后evaluateJavaScript:completionHandler的回調(diào)處理JS對于分享狀態(tài)反饋的回應(yīng)艘虎。
[self.webView evaluateJavaScript:callbackJs completionHandler:^(id _Nullable result, NSError * _Nullable error) {
if (!error) {
NSLog(@"模擬回調(diào),分享失敗");
}
}];
});
}
//選擇聯(lián)系人
else if ([message.name isEqualToString:@"nativeChoosePhoneContact"]) {
[self selectContactCompletion:^(NSString *name, NSString *phone) {
NSLog(@"選擇完成");
//讀取js function的字符串
NSString *jsFunctionString = message.body[@"completion"];
//拼接調(diào)用該方法的js字符串
NSString *callbackJs = [NSString stringWithFormat:@"(%@)({name: '%@', mobile: '%@'});", jsFunctionString, name, phone];
//執(zhí)行回調(diào)
[self.webView evaluateJavaScript:callbackJs completionHandler:^(id _Nullable result, NSError * _Nullable error) {
}];
}];
}
}
WKWebView中的屬性和方法解析
常用的屬性和方法
//設(shè)置導(dǎo)航代理
@property (nullable, nonatomic, weak) id <WKNavigationDelegate> navigationDelegate;
//設(shè)置UI代理
@property (nullable, nonatomic, weak) id <WKUIDelegate> UIDelegate;
//導(dǎo)航列表
@property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;
//通過url加載網(wǎng)頁視圖
- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;
//通過文件加載網(wǎng)頁視圖
- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL NS_AVAILABLE(10_11, 9_0);
//通過HTML字符串加載網(wǎng)頁視圖
- (nullable WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;
//通過data數(shù)據(jù)加載網(wǎng)頁視圖
- (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL NS_AVAILABLE(10_11, 9_0);
//渲染導(dǎo)航列表中的某個網(wǎng)頁節(jié)點
- (nullable WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item;
//網(wǎng)頁標(biāo)題
@property (nullable, nonatomic, readonly, copy) NSString *title;
//網(wǎng)頁的url
@property (nullable, nonatomic, readonly, copy) NSURL *URL;
//網(wǎng)頁是否正在加載中
@property (nonatomic, readonly, getter=isLoading) BOOL loading;
//加載進度 可以監(jiān)聽這個屬性的值配合UIProgressView來設(shè)計進度條
@property (nonatomic, readonly) double estimatedProgress;
//是否全部是安全連接
@property (nonatomic, readonly) BOOL hasOnlySecureContent;
//證書列表
@property (nonatomic, readonly, copy) NSArray *certificateChain;
//是否可以回退
@property (nonatomic, readonly) BOOL canGoBack;
//是否可以前進
@property (nonatomic, readonly) BOOL canGoForward;
//回退網(wǎng)頁
- (nullable WKNavigation *)goBack;
//前進網(wǎng)頁
- (nullable WKNavigation *)goForward;
//刷新網(wǎng)頁
- (nullable WKNavigation *)reload;
//忽略緩存的刷新
- (nullable WKNavigation *)reloadFromOrigin;
//停止加載
- (void)stopLoading;
//執(zhí)行JavaScript代碼
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ __nullable)(__nullable id, NSError * __nullable error))completionHandler;
//是否允許右滑返回手勢
@property (nonatomic) BOOL allowsBackForwardNavigationGestures;
WKBackForwardList類為導(dǎo)航管理的網(wǎng)頁列表類
@interface WKBackForwardList : NSObject
//當(dāng)前所在的網(wǎng)頁節(jié)點
@property (nullable, nonatomic, readonly, strong) WKBackForwardListItem *currentItem;
//前進的一個網(wǎng)頁節(jié)
@property (nullable, nonatomic, readonly, strong) WKBackForwardListItem *forwardItem;
//回退的一個網(wǎng)頁節(jié)點
@property (nullable, nonatomic, readonly, strong) WKBackForwardListItem *backItem;
//獲取某個index的網(wǎng)頁節(jié)點
- (nullable WKBackForwardListItem *)itemAtIndex:(NSInteger)index;
//獲取回退的節(jié)點數(shù)組
@property (nonatomic, readonly, copy) NSArray<WKBackForwardListItem *> *backList;
//獲取前進的節(jié)點數(shù)組
@property (nonatomic, readonly, copy) NSArray<WKBackForwardListItem *> *forwardList;
@end
WKBackForwardListItem 網(wǎng)頁節(jié)點
@interface WKBackForwardListItem : NSObject
//當(dāng)前節(jié)點的URL
@property (readonly, copy) NSURL *URL;
//當(dāng)前節(jié)點的標(biāo)題
@property (nullable, readonly, copy) NSString *title;
//創(chuàng)建此WebView的初始URL
@property (readonly, copy) NSURL *initialURL;
WKUserScript
//注入的js代碼的腳本
WKUserScript *js = [[WKUserScript alloc] initWithSource:jsSource injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:NO];
[self.webView.configuration.userContentController addUserScript:js];
/*source為要注入的js代碼
WKUserScriptInjectionTime設(shè)置注入的時機forMainFrameOnly參數(shù)設(shè)置是否只在主頁面注入
typedef NS_ENUM(NSInteger, WKUserScriptInjectionTime) {
//原js代碼運行前注入
WKUserScriptInjectionTimeAtDocumentStart,
//原js代碼運行后注入
WKUserScriptInjectionTimeAtDocumentEnd
} NS_ENUM_AVAILABLE(10_10, 8_0);
*/
- (instancetype)initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly;
WKNavagationDelegate協(xié)議
該代理提供的方法咒吐,可以用來追蹤加載過程(頁面開始加載野建、加載完成属划、加載失敗)候生、決定是否執(zhí)行跳轉(zhuǎn)同眯。
//追蹤加載過程
// 頁面開始加載時調(diào)用
-(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation;
// 當(dāng)內(nèi)容開始返回時調(diào)用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation;
// 頁面加載完成之后調(diào)用
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;
// 頁面加載失敗時調(diào)用
-(void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation;
// 頁面跳轉(zhuǎn)的代理方法有三種,分為(收到跳轉(zhuǎn)與決定是否跳轉(zhuǎn)兩種):
// 接收到服務(wù)器跳轉(zhuǎn)請求之后調(diào)用
-(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation;
// 在收到響應(yīng)后唯鸭,決定是否跳轉(zhuǎn)
-(void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
/*
在發(fā)送請求之前嗽测,決定是否跳轉(zhuǎn),決定是否響應(yīng)網(wǎng)頁的某個動作,例如加載肿孵,回退唠粥,前進,刷新等停做,在這個方法中晤愧,必須執(zhí)行decisionHandler()代碼塊,并將是否允許這個活動執(zhí)行在block中進行傳入
*//*
WKNavigationAction是網(wǎng)頁動作的抽象化蛉腌,其中封裝了許多行為信息官份,后面會介紹
WKNavigationActionPolicy為開發(fā)者回執(zhí),枚舉如下:
typedef NS_ENUM(NSInteger, WKNavigationActionPolicy) {
//取消此次行為
WKNavigationActionPolicyCancel,
//允許此次行為
WKNavigationActionPolicyAllow,
} NS_ENUM_AVAILABLE(10_10, 8_0);
*/
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
decisionHandler(WKNavigationActionPolicyAllow);
}
WKUIDelegate協(xié)議
//創(chuàng)建新的webView時調(diào)用的方法
-(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{ return webView;
}
//關(guān)閉webView時調(diào)用的方法
-(void)webViewDidClose:(WKWebView *)webView{
}
//下面這些方法是交互JavaScript的方法
//JavaScript調(diào)用alert方法后回調(diào)的方法 message中為alert提示的信息 必須要在其中調(diào)用completionHandler()
-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{ NSLog(@"%@",message);
completionHandler();
}
//JavaScript調(diào)用confirm方法后回調(diào)的方法 confirm是js中的確定框烙丛,需要在block中把用戶選擇的情況傳遞進去
-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{ NSLog(@"%@",message);
completionHandler(YES);
}
//JavaScript調(diào)用prompt方法后回調(diào)的方法 prompt是js中的輸入框 需要在block中把用戶輸入的信息傳入
-(void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{ NSLog(@"%@",prompt);
completionHandler(@"123");
}
WKNavagationAction類
@interface WKNavigationAction : NSObject
//原頁面
@property (nonatomic, readonly, copy) WKFrameInfo *sourceFrame;
//目標(biāo)頁面
@property (nullable, nonatomic, readonly, copy) WKFrameInfo *targetFrame;
//請求URL
@property (nonatomic, readonly, copy) NSURLRequest *request;
//活動類型/*typedef NS_ENUM(NSInteger, WKNavigationType) {
//鏈接激活 WKNavigationTypeLinkActivated,
//提交操作 WKNavigationTypeFormSubmitted,
//前進操作 WKNavigationTypeBackForward,
//刷新操作 WKNavigationTypeReload,
//重提交操作 例如前進 后退 刷新 WKNavigationTypeFormResubmitted,
//其他類型
WKNavigationTypeOther = -1,
} NS_ENUM_AVAILABLE(10_10, 8_0);
*/
@property (nonatomic, readonly) WKNavigationType navigationType;
@end
參考鏈接
https://www.cnblogs.com/XYQ-208910/p/5876419.html
http://www.reibang.com/p/ab58df0bd1a1
http://www.reibang.com/p/ab58df0bd1a1