2018-03-23

WKWebView基類封裝

項(xiàng)目一直使用UIWebView捉兴,相關(guān)基類方法封裝使用比較完善钓觉,業(yè)務(wù)量重,想整體替換為WKWebView有點(diǎn)難度肢娘,需要時(shí)間完善。所以我在自己的demo中初步封裝了WKWebView舆驶,參考原有的項(xiàng)目的UIWebView橱健。

BaseViewController

由于后續(xù)導(dǎo)航欄返回事件需要處理,自定義BaseViewController沙廉,自定義返回方法拘荡。代碼如下:

- (void)viewDidLoad {

? ? [super viewDidLoad];

? ? [self setBaseView];

}

- (void)setBaseView{

? ? UIBarButtonItem *item = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"title_new_back"] style:UIBarButtonItemStylePlain target:self action:@selector(backButtonAction:)];

? ? NSInteger index = [self.navigationController.viewControllers indexOfObject:self];

? ? if (index != 0) {

? ? ? ? self.navigationItem.leftBarButtonItem = item;

? ? }

}

- (void)backButtonAction:(UIBarButtonItem *)item{

? ? Class backController = NSClassFromString(self.backController);

? ? NSArray *reverseArray = [[self.navigationController.viewControllers reverseObjectEnumerator] allObjects];

? ? if (!self.backController) {

? ? ? ? [self.navigationController popViewControllerAnimated:YES];

? ? }else {

? ? ? ? for (UIViewController *controller in reverseArray) {

? ? ? ? ? ? if ([controller isKindOfClass:backController]) {

? ? ? ? ? ? ? ? [self.navigationController popToViewController:controller animated:YES];

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

viewdidload中設(shè)置導(dǎo)航欄,leftBarButtonItem的設(shè)置圖片撬陵,對(duì)應(yīng)點(diǎn)擊方法定義珊皿。

BaseWKWebViewController

然后我的BaseWKWebViewController基于BaseViewController創(chuàng)建。在.h定義幾個(gè)參數(shù)代碼如下:

/**

*@briefwkWebview

*/

@property (nonatomic, strong) WKWebView? ? ? ? ? ? ? ? *wkWebView;

/**

*@briefwkConfiguration配置

*/

@property (nonatomic, strong) WKWebViewConfiguration? ? *wkConfiguration;

/**

*@briefwebUrl

*/

@property (nonatomic, copy) NSString? ? ? ? ? ? ? ? ? ? *urlString;

對(duì)應(yīng)的webView巨税,wkWebView一些屬性設(shè)置值蟋定,加載url的地址。

然后在.m中創(chuàng)建webView草添,其中有一點(diǎn)需要注意:方法重名問題驶兜。當(dāng)初我再父類BaseViewController中和BaseWKWebView中都用setUpUi這個(gè)方法,結(jié)果父類的方法就失效了果元,被子類覆蓋了促王。所以子類創(chuàng)建視圖的方法調(diào)整為setBaseWK犀盟,具體代碼如下:

- (void)viewDidLoad {

? ? [super viewDidLoad];

? ? [self setBaseWK];

}

- (void)setBaseWK{

? ? if (!self.wkConfiguration) {

? ? ? ? self.wkConfiguration = [[WKWebViewConfiguration alloc]init];

? ? ? ? //設(shè)置一些屬性

? ? }

? ? self.wkWebView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) configuration:self.wkConfiguration];

? ? self.wkWebView.UIDelegate = self;

? ? self.wkWebView.navigationDelegate = self;

? ? self.wkWebView.allowsBackForwardNavigationGestures = YES;

? ? [self.view addSubview:self.wkWebView];

? ? [self.wkWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.urlString]]];

? ? [self.wkWebView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];

}

創(chuàng)建WKWebView而晒,設(shè)置它的兩個(gè)代理:UIDelegate和navigationDelegate。代理方法稍后再講阅畴。allowsBackForwardNavigationGestures這個(gè)屬性是控制webView側(cè)滑返回的倡怎,默認(rèn)是NO,設(shè)置為YES后贱枣,web頁(yè)面能像原生頁(yè)面一樣策劃返回了监署。然后將webView加到當(dāng)前視圖,加載對(duì)應(yīng)的url地址纽哥。最后是網(wǎng)上看到的方法钠乏,利用KVO設(shè)置WKWebView的title,相比較UIWebView的設(shè)置這個(gè)有一絲繁瑣春塌,具體代碼稍后提及晓避。

UIDelegate

- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{

在這個(gè)方法中寫如下代碼:

if (!navigationAction.targetFrame.isMainFrame) {

? ? ? ? [webView loadRequest:navigationAction.request];

? ? }

? ? return nil;

WKNavigationDelegate

這個(gè)代理里面寫了三個(gè)方法:

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{

didFinishNavigation就是完成加載webView時(shí)候的方法簇捍。后面兩個(gè)對(duì)應(yīng)UIWebView中的shouldLoad,將要加載方法俏拱。WK中分為請(qǐng)求發(fā)起前即navigationAction和接口請(qǐng)求相應(yīng)后navigationResponse暑塑。對(duì)面方法下面允許加載,不然url不會(huì)跳轉(zhuǎn)锅必。

KVO設(shè)置WKWebView的title

代碼如下:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{

? ? if ([keyPath isEqualToString:@"title"]) {

? ? ? ? if (object == self.wkWebView) {

? ? ? ? ? ? self.title = self.wkWebView.title;

? ? ? ? }else {

? ? ? ? ? ? [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];

? ? ? ? }

? ? }else {

? ? ? ? [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];

? ? }

}

- (void)dealloc{

? ? [self.wkWebView removeObserver:self forKeyPath:@"title"];

}

注意在dealloc中移除KVO事格。

返回問題

重寫父類的backButton方法:

- (void)backButtonAction:(UIBarButtonItem *)item{

? ? if ([self.wkWebView canGoBack]) {

? ? ? ? [self.wkWebView goBack];

? ? }else {

? ? ? ? [self.navigationController popViewControllerAnimated:YES];

? ? }

}

當(dāng)web頁(yè)面多次進(jìn)入跳轉(zhuǎn)新頁(yè)面后,為了防止逐級(jí)返回搞隐,參考老項(xiàng)目做了close按鈕操作驹愚。當(dāng)判斷當(dāng)前頁(yè)面是要做回退跳轉(zhuǎn)的時(shí)候,在左上角增加關(guān)閉當(dāng)前web控制器的按鈕劣纲。代買如下:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{

? ? if (navigationAction.navigationType == WKNavigationTypeBackForward) {

? ? ? ? [self addCloseItemAction];

? ? }

- (void)addCloseItemAction{

? ? if (self.navigationItem.leftBarButtonItems.count<2) {


? ? ? ? UIButton* closeButton = [UIButton buttonWithType:UIButtonTypeCustom];


? ? ? ? [closeButton setImage:[UIImage imageNamed:@"title_new_close"] forState:UIControlStateNormal];

? ? ? ? closeButton.frame = CGRectMake(0, 0, 30, 30);

? ? ? ? [closeButton addTarget:self action:@selector(closeWeb) forControlEvents:UIControlEventTouchUpInside];


? ? ? ? UIBarButtonItem* closeBarItem = [[UIBarButtonItem alloc] initWithCustomView:closeButton];


? ? ? ? self.navigationItem.leftBarButtonItems = @[self.navigationItem.leftBarButtonItem,closeBarItem];

? ? }

}

- (void)closeWeb{

? ? [self.navigationController popToRootViewControllerAnimated:YES];

}

這樣返回操作就得到了優(yōu)化么鹤。

WKTestWebViewController

最后我用WKTestWebViewController基于WKWebViewController創(chuàng)建相關(guān)web頁(yè)面對(duì)之前代碼進(jìn)行校驗(yàn),返現(xiàn)能夠跳轉(zhuǎn)味廊,但是在WKTestWebViewController中如果再寫UIDelegate和NavigationDelegate的時(shí)候蒸甜,發(fā)現(xiàn)父類的方法又被覆蓋了,所以將父類實(shí)現(xiàn)的wk代理方法代理出來余佛。對(duì)WKWebViewController做操作:在.h中添加代理柠新,對(duì)應(yīng).m實(shí)現(xiàn)代碼如下:

.h添加代理

@protocol GFWKWebViewDelegate;

@interface BaseWKWebViewController : BaseViewController

/**

*@briefGFwkWebDelegate

*/

@property (nonatomic, weak) id? ? wkWebDelegate;

@end

@protocol GFWKWebViewDelegate

@optional

//wkUIDelegate

- (WKWebView *)GF_webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;

//wkNavigationDelegate

- (void)GF_webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;

- (void)GF_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;

- (void)GF_webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;

@end

.m實(shí)現(xiàn)代理

UIDelegate

- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{

? ? if (self.wkWebDelegate && [self.wkWebDelegate respondsToSelector:@selector(GF_webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:)]) {

? ? ? ? [self.wkWebDelegate GF_webView:webView createWebViewWithConfiguration:configuration forNavigationAction:navigationAction windowFeatures:windowFeatures];

? ? }

NavigationDelegate

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{

? ? if (self.wkWebDelegate && [self.wkWebDelegate respondsToSelector:@selector(GF_webView:didFinishNavigation:)]) {

? ? ? ? [self.wkWebDelegate GF_webView:webView didFinishNavigation:navigation];

? ? }

}

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{


? ? if (self.wkWebDelegate && [self.wkWebDelegate respondsToSelector:(@selector(GF_webView:decidePolicyForNavigationAction:decisionHandler:))]) {

? ? ? ? [self.wkWebDelegate GF_webView:webView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler];

? ? }

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{

? ? decisionHandler(WKNavigationResponsePolicyAllow);

? ? if (self.wkWebDelegate && [self.wkWebDelegate respondsToSelector:@selector(GF_webView:decidePolicyForNavigationResponse:decisionHandler:)]) {

? ? ? ? [self.wkWebDelegate GF_webView:webView decidePolicyForNavigationResponse:navigationResponse decisionHandler:decisionHandler];

? ? }

}

這樣四個(gè)方法都實(shí)現(xiàn)了,其實(shí)只要實(shí)現(xiàn)子類用到的方法就好了辉巡。當(dāng)然如果父類在做統(tǒng)一設(shè)置恨憎,實(shí)現(xiàn)了相關(guān)wk代理的方法,需要后續(xù)再完善郊楣。

代理使用

在WKTestWebViewController使用父類設(shè)置的代理憔恳,頭文件中引入代理,設(shè)置代理等于self净蚤,對(duì)應(yīng)代理方法調(diào)整钥组,代碼如下:

@interface WKTestWebViewController ()<GFWKWebViewDelegate>

@end

@implementation WKTestWebViewController

- (void)viewDidLoad {

? ? [super viewDidLoad];

? ? [self setTestWK];

}

- (void)setTestWK{

? ? self.wkWebDelegate = self;

}

#pragma mark GFWKWebView UIDelegate

- (void)GF_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{

? ? NSLog(@"%ld", (long)navigationAction.navigationType);

//? ? decisionHandler(WKNavigationActionPolicyAllow);

}

注意子類代理方法中不能在寫decisionHandler(WKNavigationActionPolicyAllow),不然報(bào)錯(cuò)重復(fù)decisionHandler今瀑。這樣就能在實(shí)現(xiàn)父類返回關(guān)閉功能以及未來需要統(tǒng)一增加的功能同時(shí)程梦,還能完成具體子類個(gè)性化處理。

總結(jié)

如上就是我對(duì)WKWebView相關(guān)認(rèn)識(shí)橘荠,期間的父類子類重名問題卡了一段時(shí)間屿附,后續(xù)功能方法的優(yōu)化需要再實(shí)踐中逐步完善。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末哥童,一起剝皮案震驚了整個(gè)濱河市挺份,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贮懈,老刑警劉巖匀泊,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件影暴,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡探赫,警方通過查閱死者的電腦和手機(jī)型宙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來伦吠,“玉大人妆兑,你說我怎么就攤上這事∶牵” “怎么了搁嗓?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)箱靴。 經(jīng)常有香客問我腺逛,道長(zhǎng),這世上最難降的妖魔是什么衡怀? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任棍矛,我火速辦了婚禮,結(jié)果婚禮上抛杨,老公的妹妹穿的比我還像新娘够委。我一直安慰自己,他們只是感情好怖现,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布茁帽。 她就那樣靜靜地躺著,像睡著了一般屈嗤。 火紅的嫁衣襯著肌膚如雪潘拨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天饶号,我揣著相機(jī)與錄音铁追,去河邊找鬼。 笑死讨韭,一個(gè)胖子當(dāng)著我的面吹牛脂信,可吹牛的內(nèi)容都是我干的癣蟋。 我是一名探鬼主播透硝,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼疯搅!你這毒婦竟也來了濒生?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤幔欧,失蹤者是張志新(化名)和其女友劉穎罪治,沒想到半個(gè)月后丽声,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡觉义,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年雁社,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晒骇。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡霉撵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出洪囤,到底是詐尸還是另有隱情徒坡,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布瘤缩,位于F島的核電站喇完,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏剥啤。R本人自食惡果不足惜锦溪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望府怯。 院中可真熱鬧海洼,春花似錦、人聲如沸富腊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)赘被。三九已至是整,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間民假,已是汗流浹背浮入。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留羊异,地道東北人事秀。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像野舶,于是被迫代替她去往敵國(guó)和親易迹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

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

  • 前言 關(guān)于UIWebView的介紹平道,相信看過上文的小伙伴們睹欲,已經(jīng)大概清楚了吧,如果有問題,歡迎提問窘疮。 本文是本系列...
    CoderLF閱讀 8,943評(píng)論 2 12
  • 原文地址 前言 Web 頁(yè)面中的 JS 與 iOS Native 如何交互是每個(gè) iOS 猿必須掌握的技能袋哼。而 J...
    小嘴冰涼別亂親閱讀 1,853評(píng)論 2 5
  • WKWebView是在Apple的WWDC 2014隨iOS 8和OS X 10.10出來的,是為了解決UIWeb...
    zhYx_閱讀 22,633評(píng)論 4 19
  • WebViewJavascriptBridge應(yīng)該是當(dāng)前最流行最成功的OC與Web交互實(shí)現(xiàn)了闸衫。最近看了一下他的實(shí)現(xiàn)...
    廖丹_18be閱讀 3,116評(píng)論 0 4
  • 之前在書上看到一句話涛贯,“所有的分手,都是為了遇見真愛”蔚出。我不知道怎么表述自己的想法疫蔓,今天和他分手了,我談過很多男朋...
    區(qū)染閱讀 269評(píng)論 0 0