目錄
-WKWebView 初始化
-WKWebView 加載資源
-WKWebView WKNavigationDelegate
-WKWebView 原生與JS交互實(shí)現(xiàn)
-WKWebView 第三方庫(kù)實(shí)現(xiàn)原理
一、WKWebView初始化
1、方法一,簡(jiǎn)單初始化
WKWebView *webView = [ [WKWebView alloc]initWithFrame:[UIScreen mainScreen].bounds];
2、方法二,使用WKWebViewConfiguration初始化
WKWebViewConfigration *webViewConfigration = [[WKWebViewConfigration alloc]init];
webViewConfigration.userContentController = [[WKUserContentController alloc]init];
WKWebView *webView = [ [WKWebView alloc]initWithFrame:[UIScreen mainScreen].bounds configration:webViewConfigration];
二、WKWebView 加載資源
1、加載網(wǎng)絡(luò)資源
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/"];
NSURLRequest = [NSURLRequest requestWithURL:url];
[webView loadRequest:url];
2、加載本地資源
NSString *path = [[NSBundle mainBundle] pathForResource:@"index" type: @"HTML"];
NSString *htmlString = [NSString stringWithContentOfFile:path encoding: NSUTF8StringEncoding error:nil];
[webView loadHTMLString:htmlString baseURL:baseUrl];
請(qǐng)注意: 這里有坑!!有坑!!有坑?。?!如果是從Bundle獲取的文件是有問題的 移步這里http://www.lxweimin.com/p/92776cd5b098(雖然語言是swift寫的,問題是同樣的問題)
三、WKNavigationDelegate代理
1、 (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSLog(@"是否允許這個(gè)導(dǎo)航");
decisionHandler(WKNavigationActionPolicyAllow);
}
這個(gè)方法是加載網(wǎng)頁(yè)第一個(gè)執(zhí)行的方法,因?yàn)樗_定是否允許或者取消加載這個(gè)頁(yè)面。這里有一個(gè)枚舉WKNavigationActionPolicy,其結(jié)構(gòu)如下:
typedef NS_ENUM(NSInteger, WKNavigationActionPolicy) {
WKNavigationActionPolicyCancel,
WKNavigationActionPolicyAllow,
} API_AVAILABLE(macosx(10.10), ios(8.0));
-
(void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
// Decides whether to allow or cancel a navigation after its response is known.NSLog(@"知道返回內(nèi)容之后,是否允許加載,允許加載");
//這個(gè)Block必須執(zhí)行,不然會(huì)崩潰
decisionHandler(WKNavigationResponsePolicyAllow);
}
2、 (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
NSLog(@"開始加載");
self.progress.alpha = 1;
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}
這個(gè)方法比較好理解,就是當(dāng)網(wǎng)頁(yè)內(nèi)容開始加載到web view的時(shí)候調(diào)用
3、(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
NSLog(@"跳轉(zhuǎn)到其他的服務(wù)器");
}
這個(gè)代理方法了。我們知道了網(wǎng)頁(yè)是否允許加載,那么一旦不允許,那么這個(gè)加載過程就已經(jīng)結(jié)束了,不會(huì)再執(zhí)行其他的代理方法;如果允許,那么就會(huì)執(zhí)行開始加載的代理方法,執(zhí)行完開始加載的代理方法的時(shí)候再執(zhí)行這個(gè)代理方法
4、 (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
NSLog(@"網(wǎng)頁(yè)由于某些原因加載失敗");
self.progress.alpha = 0;
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
5、 (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation {
NSLog(@"網(wǎng)頁(yè)開始接收網(wǎng)頁(yè)內(nèi)容");
}
這個(gè)代理方法是在網(wǎng)頁(yè)開始接受網(wǎng)絡(luò)內(nèi)容的時(shí)候調(diào)用
6、(void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
NSLog(@"網(wǎng)頁(yè)導(dǎo)航加載完畢");
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
self.title = webView.title;
[webView evaluateJavaScript:@"document.title" completionHandler:^(id _Nullable ss, NSError * _Nullable error) {
NSLog(@"----document.title:%@---webView title:%@",ss,webView.title);
}];
self.progress.alpha = 0;
}
網(wǎng)頁(yè)已經(jīng)加載完畢會(huì)調(diào)用這個(gè)代理方法
7、 (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
NSLog(@"加載失敗,失敗原因:%@",[error description]);
self.progress.alpha = 0;
}
網(wǎng)頁(yè)加載失敗會(huì)調(diào)用的代理
8、 (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView {
NSLog(@"網(wǎng)頁(yè)加載內(nèi)容進(jìn)程終止");
}
9、 (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
}
網(wǎng)頁(yè)重定向會(huì)調(diào)用
四、WKWebView 原生與JS交互實(shí)現(xiàn)
1、js給原生發(fā)送消息
方法一,js通過觸發(fā)URL的方式,定義一套協(xié)議頭,把參數(shù)拼接到URL后面,然后WKWebView通過攔截URL,做到傳值效果,但是不能立馬拿到返回值,因?yàn)閖s是單線程的,而在原生里面則是多線程,如果要想拿到返回值,需要等到原聲回調(diào)js函數(shù)才能拿到
上代碼:
js代碼,簡(jiǎn)單點(diǎn)的吧
<a href="webview://login?username=xiaoming&password=123456">點(diǎn)我去原生登陸</a>
oc代碼,WKWebViewNavigationDelegate代理方法
-
(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURL url = navigation.request.url;
if ([[url scheme] isEqualToString: @"webview"]) {
//取出拼接在URL后面的參數(shù)
NSString *string = url.absoluteString;
NSArray *array = [string compoentsSeparatedByString:@"?"];
if(array.count>0){
if([array[0] isEqualToString:@"login"]) {
//獲取登陸 參數(shù)
NSMutableDictionary * parameters = [NSMutableDictionary Dictionary];
for(NSString *str in [array.lastObject compoentsSeparatedByString:@"&"]) {
NSArray * parameter = [str compoentsSeparatedByString:@"="];
parameters[parameter.firstObject] = parameter.lastObject;
}}
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
decisionHandler(WKNavigationActionPolicyAllow);
}
方法二、通過js通過調(diào)用這個(gè)函數(shù)來給wkwebview發(fā)送消息 window.webkit.messageHandlers.<name>.postMessage(<messageBody>) ,在WKUserContentController.h 文件中有介紹,其中<name>為協(xié)議的名稱,<messageBody>為發(fā)送消息要傳的參數(shù)
例如,:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>oc與JS交互傳值Demo</title>
<script>
function sendMessage() {
alert('lll');
var name = 'xiaoming';
var password = '123456';
window.webkit.login.postMessage({'name':name,'password':password});
}
window.onload = function () {
let btn = document.getElementById('btn');
btn.onclick = sendMessage;
}
</script>
</head>
<body>
<input type="button" value="發(fā)消息去" id="btn">
</body>
</html>
這是一個(gè)簡(jiǎn)單的html
oc中接收js消息代碼
//初始化
WKWebViewConfigration *webViewConfigration = [[WKWebViewConfigration alloc]init];
webViewConfigration.userContentController = [[WKUserContentController alloc]init];
webViewConfigration.userContentController
WKWebView *webView = [ [WKWebView alloc]initWithFrame:[UIScreen mainScreen].bounds configration:webViewConfigration];
//添加一個(gè)協(xié)議
[webViewConfigration.userContentController addScriptMessageHandler:self name:@"login"];
self必須遵守WKScriptMessageHandler協(xié)議并實(shí)現(xiàn)方法
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
//messag.name為協(xié)議的名字"login"
//message.body為js傳過來的值
}
2、oc給js發(fā)送消息
采用蘋果提供的接口,可以動(dòng)態(tài)注入js代碼,也能調(diào)用js方法
oc代碼如下:
[_webView evaluateJavaScript:@"outLogin(true)" completionHandler:^(id _Nullable meassge, NSError * _Nullable error) {
//消息執(zhí)行完成的回調(diào)
}];
js代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>oc與JS交互傳值Demo</title>
<script>
function outLogin(meassge) {
//退出登錄,清理緩存
return true;
}
</script>
</head>
<body>
</body>
</html>
先到此下一篇講WKWebViewJavaScriptBridge解析,也是基于原生代碼的封裝