前言
隨著H5的發(fā)展,在iOS開發(fā)中,網(wǎng)頁視圖的使用率逐漸提升,為了增加代碼封裝度、減輕開發(fā)負(fù)擔(dān),因此通常會對網(wǎng)頁視圖進行通用類的封裝,本文簡單講述網(wǎng)頁視圖控制器通用類的封裝流程,希望對大家有所幫助。
需要解決的問題:
版本適配(UIWebView&&WKWebView)
導(dǎo)航按鈕快捷設(shè)置(返回&&關(guān)閉)
修復(fù)自定義導(dǎo)航按鈕側(cè)滑手勢失效問題
側(cè)滑手勢返回上層網(wǎng)頁功能
網(wǎng)頁加載進度顯示
網(wǎng)頁下拉刷新
請求異常占位圖
HTTPS認(rèn)證
效果圖演示

一、版本適配問題
在真實的開發(fā)中我們可能對UIWebView“愛不釋手”,因其調(diào)用簡單,使用方便,但其會占用程序的大量內(nèi)存,加載速度慢,體驗效果并不是很好,WKWebView為iOS8推出的網(wǎng)頁展示視圖,相比UIWebView,其占用的內(nèi)存更小,請求效率更高,因此極力推薦大家使用WKWebView。
因此在網(wǎng)頁視圖的創(chuàng)建方面首先進行版本適配,對于大于iOS8的系統(tǒng)我們采用WKWebView,反之使用UIWebView。
- (void)createWebView {
self.automaticallyAdjustsScrollViewInsets = NO;
if ([[[UIDevice currentDevice]systemVersion]floatValue] >= 8.0) {
[self.view addSubview:self.wk_WebView];
?} else {
[self.view addSubview:self.webView];
?}
}
二、導(dǎo)航按鈕快捷設(shè)置(返回&&關(guān)閉)
該功能的實現(xiàn)比較簡單,我們可以根據(jù)webView或wk_webView的goBack方法進行判斷,檢測當(dāng)前網(wǎng)頁是否存在可返回的上一界面,若存在顯示返回與關(guān)閉按鈕,若不存在顯示返回按鈕即可。
- (void)showLeftBarButtonItem {
if ([_webView canGoBack] || [_wk_WebView canGoBack]) {
self.navigationItem.leftBarButtonItems = @[self.backBarButtonItem,self.closeBarButtonItem];
} else {
self.navigationItem.leftBarButtonItem = self.backBarButtonItem;
?}
}
closeBarButtonItem所處理的事件為關(guān)閉界面操作即
- (void)close:(UIBarButtonItem*)item {
[self.navigationController popViewControllerAnimated:YES];
}
backBarButtonItem需根據(jù)網(wǎng)頁是否可返回前一界面觸發(fā)返回前界面或關(guān)閉操作
- (void)back:(UIBarButtonItem*)item {
if ([_webView canGoBack] || [_wk_WebView canGoBack]) {
[_webView goBack];
[_wk_WebView goBack];
} else {
[self.navigationController popViewControllerAnimated:YES];
?}
}
在這里我們也可以對導(dǎo)航欄標(biāo)題進行設(shè)置,使其為當(dāng)前網(wǎng)頁標(biāo)題,在網(wǎng)頁加載完成方法中簡單調(diào)用JS語句document.title即可,webView與WkWebView調(diào)用JS方法有所區(qū)別,如下代碼所示:
//WebView
self.navigationItem.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
//WkWebView
[webView evaluateJavaScript:@"document.title" completionHandler:^(id _Nullable title, NSError * _Nullable error) {
self.navigationItem.title = title;
}];
對于WKWebView我們還可以通過監(jiān)聽title屬性進行實現(xiàn)。
三、修復(fù)自定義導(dǎo)航按鈕側(cè)滑手勢失效
在第二步我們手動設(shè)置了導(dǎo)航欄左按鈕,因此我們會發(fā)現(xiàn)系統(tǒng)自帶的側(cè)滑返回功能失效了,為了可實現(xiàn)網(wǎng)頁的側(cè)滑返回功能,我們需要修復(fù)其失效的問題。
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (self.navigationController.viewControllers.count > 1) {
self.delegate = self.navigationController.interactivePopGestureRecognizer.delegate;
self.navigationController.interactivePopGestureRecognizer.delegate = self;
? }?
?}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.navigationController.interactivePopGestureRecognizer.delegate = self.delegate;
?}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
return self.navigationController.viewControllers.count > 1;
?}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return self.navigationController.viewControllers.count > 1;
}
四、側(cè)滑手勢返回上層網(wǎng)頁功能
對于WKWebView系統(tǒng)為我們提供了很好的一種實現(xiàn)效果,設(shè)置WkWebView的allowsBackForwardNavigationGestures為YES即可開啟屏幕左邊緣右滑返回與屏幕右邊緣左滑返回效果。(PS:樓主曾花費一整天的時間嘗試實現(xiàn)這個效果,沒想到蘋果已準(zhǔn)備好了(╯‵□′)╯︵┻━┻ )
_wk_WebView.allowsBackForwardNavigationGestures = YES;
五、網(wǎng)頁加載進度顯示功能
對于WKWebView我們可以使用KVO監(jiān)聽屬性estimatedProgress即可獲取加載進度的變化,而對于UIWebView推薦使用NJKWebViewProgress進行添加。
[_wk_WebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:NULL];- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void *)context {
if ([keyPath isEqualToString:@"estimatedProgress"]) {
_loadingProgressView.progress = [change[@"new"] floatValue];
if (_loadingProgressView.progress == 1.0) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
_loadingProgressView.hidden = YES;
? ?});
? }
?}
}
既然添加了監(jiān)聽,因此不要忘記在dealloc中進行移除
- (void)dealloc {
[_wk_WebView removeObserver:self forKeyPath:@"estimatedProgress"];
}
六、網(wǎng)頁下拉刷新(iOS10新特性)
iOS10中為ScrollView添加了下拉刷新控件,而WebView里層控件即為ScrollView,因此我們可以為網(wǎng)頁添加下拉刷新功能。這里選擇使用系統(tǒng)原生控件UIRefreshControl,考慮某些網(wǎng)頁頁面并不需要下拉刷新功能,因此已公開BOOL加以限制,如需要可手動置為YES。
//添加下拉刷新
if ([[[UIDevice currentDevice]systemVersion]floatValue] >= 10.0 && _canDownRefresh) {
_wk_WebView.scrollView.refreshControl = self.refreshControl;
}
七、請求異常占位圖問題
在網(wǎng)址請求失敗或顯示空白頁面時需顯示占位圖提示用戶。我們分別需要在網(wǎng)頁請求失敗以及開始加載時加以判斷。以WKWebView為例。
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error{
webView.hidden = YES;
}
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation{
webView.hidden = NO;
_loadingProgressView.hidden = NO;
//不加在空白網(wǎng)頁
if ([webView.URL.scheme isEqual:@"about"]) {
webView.hidden = YES;
}
}
八、HTTPS認(rèn)證
在WKWebView中,WKNavigationDelegate中提供了一個權(quán)限認(rèn)證的代理方法,這使得權(quán)限認(rèn)證更為簡單。
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
if ([challenge previousFailureCount] == 0) {
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
} else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}
}else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
? ? ? ? ?}
}
至此,一個簡單的網(wǎng)頁視圖控制器即初步封裝完畢。后續(xù)會添加常用JS詳細(xì)操作模塊
demo已上傳GitHub網(wǎng)頁視圖控制器封裝流程demo