IOS進(jìn)階之WKWebView

基本使用方法
WKWebView有兩個delegate,WKUIDelegateWKNavigationDelegate。WKNavigationDelegate主要處理一些跳轉(zhuǎn)、加載處理操作,WKUIDelegate主要處理JS腳本,確認(rèn)框,警告框等。因此WKNavigationDelegate更加常用。
比較常用的方法:

#pragma mark - lifeCircle
- (void)viewDidLoad { 
[super viewDidLoad]; 
webView = [[WKWebView alloc]init]; 
[self.view addSubview:webView]; 
[webView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.view); make.right.equalTo(self.view); make.top.equalTo(self.view); make.bottom.equalTo(self.view); 
}]; 
webView.UIDelegate = self; 
webView.navigationDelegate = self; 
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]];
}
#pragma mark- WKNavigationDelegate
// 頁面開始加載時調(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{
}
// 接收到服務(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{
 NSLog(@"%@",navigationResponse.response.URL.absoluteString);
 //允許跳轉(zhuǎn) 
decisionHandler(WKNavigationResponsePolicyAllow); 
//不允許跳轉(zhuǎn) 
//decisionHandler(WKNavigationResponsePolicyCancel);
}
// 在發(fā)送請求之前,決定是否跳轉(zhuǎn)
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{ NSLog(@"%@",navigationAction.request.URL.absoluteString); 
//允許跳轉(zhuǎn) 
decisionHandler(WKNavigationActionPolicyAllow); 
//不允許跳轉(zhuǎn) //decisionHandler(WKNavigationActionPolicyCancel);
}
#pragma mark - WKUIDelegate
// 創(chuàng)建一個新的WebView
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{ 
  return [[WKWebView alloc]init];
}
// 輸入框
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler{ 
  completionHandler(@"http");
}
// 確認(rèn)框
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler{ 
  completionHandler(YES);
}
// 警告框
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{ 
NSLog(@"%@",message); completionHandler();
}

OC與JS交互
WKWebview提供了API實現(xiàn)js交互 不需要借助JavaScriptCore或者webJavaScriptBridge。使用WKUserContentController實現(xiàn)js native交互。簡單的說就是先注冊約定好的方法,然后再調(diào)用。

JS調(diào)用OC方法
oc代碼(有誤,內(nèi)存不釋放):

@interface ViewController ()<WKUIDelegate,WKNavigationDelegate,WKScriptMessageHandler>
{ 
WKWebView * webView;
 WKUserContentController* userContentController;
}
@end
@implementation ViewController
#pragma mark - lifeCircle
- (void)viewDidLoad {
 [super viewDidLoad]; 
//配置環(huán)境 
WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init];
userContentController =[[WKUserContentController alloc]init]; 
configuration.userContentController = userContentController;
webView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, 100, 100) configuration:configuration]; 
//注冊方法 
[userContentController addScriptMessageHandler:self name:@"sayhello"];
//注冊一個name為sayhello的js方法
 [self.view addSubview:webView]; 
[webView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.view); make.right.equalTo(self.view); make.top.equalTo(self.view); make.bottom.equalTo(self.view); 
}]; 
webView.UIDelegate = self; 
webView.navigationDelegate = self; 
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.test.com"]]];
}
- (void)dealloc{ 
//這里需要注意,前面增加過的方法一定要remove掉。 [userContentController removeScriptMessageHandlerForName:@"sayhello"];}
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{ 
NSLog(@"name:%@\\\\n body:%@\\\\n frameInfo:%@\\\\n",message.name,message.body,message.frameInfo);
}
@end

上面的OC代碼如果認(rèn)證測試一下就會發(fā)現(xiàn)dealloc并不會執(zhí)行,這樣肯定是不行的,會造成內(nèi)存泄漏。原因是[userContentController addScriptMessageHandler:self name:@"sayhello"];這句代碼造成無法釋放內(nèi)存。(ps:試了下用weak指針還是不能釋放,不知道是什么原因。)因此還需要進(jìn)一步改進(jìn),正確的寫法是用一個新的controller來處理,新的controller再繞用delegate繞回來。

oc代碼(正確寫法):

@interface ViewController ()<WKUIDelegate,WKNavigationDelegate,WKScriptMessageHandler>
{ 
WKWebView * webView; 
WKUserContentController* userContentController;
}
@end
@implementation ViewController
#pragma mark - lifeCircle
- (void)viewDidLoad { 
[super viewDidLoad]; 
//配置環(huán)境 
WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init]; 
userContentController =[[WKUserContentController alloc]init]; configuration.userContentController = userContentController; 
webView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, 100, 100) configuration:configuration]; 
//注冊方法 WKDelegateController * delegateController = [[WKDelegateController alloc]init]; 
delegateController.delegate = self; 
[userContentController addScriptMessageHandler:delegateController name:@"sayhello"]; 
[self.view addSubview:webView]; 
[webView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.view); make.right.equalTo(self.view); make.top.equalTo(self.view); make.bottom.equalTo(self.view); 
}]; 
webView.UIDelegate = self; 
webView.navigationDelegate = self;
 [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.test.com"]]];
}
- (void)dealloc{ 
//這里需要注意,前面增加過的方法一定要remove掉。 [userContentController removeScriptMessageHandlerForName:@"sayhello"];
}
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{ 
NSLog(@"name:%@\\\\n body:%@\\\\n frameInfo:%@\\\\n",message.name,message.body,message.frameInfo);
}
@end

WKDelegateController代碼:

#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
@protocol WKDelegate <NSObject>
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
@end
@interface WKDelegateController : UIViewController <WKScriptMessageHandler>
@property (weak , nonatomic) id<WKDelegate> delegate;
@end

.m代碼:

#import "WKDelegateController.h"
@interface WKDelegateController ()
@end
@implementation WKDelegateController
- (void)viewDidLoad {
 [super viewDidLoad];
}
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{ 
if ([self.delegate respondsToSelector:@selector(userContentController:didReceiveScriptMessage:)]) { 
  [self.delegate userContentController:userContentController didReceiveScriptMessage:message];
 }
}
@end

h5代碼:

<html><head> <script>function say(){//前端需要用 window.webkit.messageHandlers.注冊的方法名.postMessage({body:傳輸?shù)臄?shù)據(jù)} 來給native發(fā)送消息 window.webkit.messageHandlers.sayhello.postMessage({body: 'hello world!'});}</script></head> <body> <h1>hello world</h1> <button onclick="say()">say hello</button> </body></html>

打印出的log:

 name:sayhello
 body:{ 
  body = "hello world!";
} 
frameInfo:<WKFrameInfo: 0x7f872060ce20; isMainFrame = YES;
 request = <NSMutableURLRequest: 0x618000010a30> { URL: http://www.test.com/ }>

WebViewJavascriptBridge
一般來說,一個好的UI總有一個大神會開發(fā)出一個好的第三方封裝框架。WebViewJavascriptBridge的作者也做了一套支持WKWebView與JS交互的第三方框架:WKWebViewJavascriptBridge。
cocoaPods: pod 'WebViewJavascriptBridge', '~> 5.0.5'

github地址:https://github.com/marcuswestin/WebViewJavascriptBridge

主要方法如下:

//初始化方法
+ (instancetype)bridgeForWebView:(WKWebView*)webView;
+ (void)enableLogging;
//注冊函數(shù)名
- (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler;
//調(diào)用函數(shù)名
- (void)callHandler:(NSString*)handlerName;
- (void)callHandler:(NSString*)handlerName data:(id)data;
- (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback;
//重置
- (void)reset;
//設(shè)置WKNavigationDelegate
- (void)setWebViewDelegate:(id<WKNavigationDelegate>)webViewDelegate;

基本的實現(xiàn)方法和上面寫的差不多,就是封裝了一下,有興趣的童鞋可以自己pod下來使用。
轉(zhuǎn)載請保留原文鏈接!!!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,460評論 6 538
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,067評論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,467評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,468評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,184評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,582評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,616評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,794評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,343評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,096評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,291評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,863評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,513評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,941評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,190評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,026評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,253評論 2 375

推薦閱讀更多精彩內(nèi)容