WKViewManager iOS 彈窗架構

前言

近來因爲App中彈窗過多,再加上還有半透明的引導層,時常會出現多個彈窗重疊彈出,甚至會伴隨引導層一塊兒彈出,極大的影響了用戶體驗。git

上述問題,其實很簡單,只須要添加一個彈窗隊列便可。github

可是與此同時咱們又添加了新的需求以下:數據庫

  1. 廣告彈窗不能出如今閱讀頁
  2. 訂閱更新彈窗只能出如今首頁
  3. 版本更新功能提示頁不容許出現任何彈窗
  4. 從新安裝後出現的選擇性別和分類的彈窗不容許出現任何彈窗
  5. 廣告觀賞頁面不能出現任何彈窗
  6. 因爲廣告和公告頁面的彈出順序不定,當彈出廣告時,廣告視圖可點擊產生跳轉,可是在跳轉後公告會彈出(公告具有倒計時只顯示多少秒,而後自動消失),則會出現公告沒法被用戶看到的狀況,則須要在跳轉離開頁面時,暫停隊列

因爲項目中咱們採用了模塊化的方式精簡代碼、下降工做耦合,因此咱們的彈窗並非基於ViewController彈出的,而是在須要彈出的時候獲取當前顯示的ViewController用於顯示的。數組

例如項目中任務模塊,任務是能夠在任何地方任什麼時候候被完成,任務自己不關心它是位於什麼時候何地被完成,只須要關心完成後,須要對應作出什麼操做,例如寫本地數據庫,更新用戶數據,彈出完成任務提示,和ViewController並沒有大的關聯。bash

簡單的說,咱們的彈窗是屬於功能塊的,而功能塊不該該且不用去關心當前展現的ViewController是哪個。架構

功能介紹

本文介紹的一個彈窗架構實際也能夠歸類爲一個彈窗功能模塊,當彈窗出如今不應出現的地方時,它來負責調度和處理,其過程對於其它功能模塊透明,並不產生任何耦合度。其實現功能以下:app

  1. 彈窗視圖按隊列依次出現
  2. 彈窗視圖支持優先級模式
  3. 隊列基於ViewController,杜絕一個彈窗問題致使全局彈窗失效
  4. 彈窗視圖可指定出現於某ViewController出現後(白名單)
  5. ViewController可指定不接收彈窗視圖出現於自身出現時(黑名單)
  6. 實現ViewController didDisAppear後 隊列暫停,willAppear隊列繼續
優勢

WKViewManager 彈窗隊列管理類,使用AOP切片基於self-manager模式封裝,高內聚性,幾乎不會和ViewController或功能模塊產生耦合。ide

劣勢

因爲是彈窗視圖的一個管理工具,全部須要被管理的彈窗均需屬於WKBaseView的子類,項目中已書寫對應所須要的彈窗基類如WKPopBaseView、WKStepMaskGuideView等等,有須要構建彈窗的時候能夠去查看相關類。模塊化

(關於WKBaseView,是一個封裝的很是完善的彈窗基類,預計後續會寫一篇文章詳細介紹,它的整個結構是很是完善,針對彈窗功能幾乎沒有擴充瓶頸)工具

實現原理

白名單模式(功能點4)

白名單模式只有一個關鍵內容

白名單字典 - whiteList
複製代碼

白名單字典位於WKViewManager類中。

字典中key爲從屬於WKBaseView的子類的類名字符串,value是一個數組,裏面放入對應的ViewController的類名字符串。

例如 白名單內容爲

@{@"KMAnnouncementView":@[@"HJTMainTabBarVC"]};
複製代碼

則在廣告公告模塊中,KMAnnouncementView調用顯示時,所獲取的View不是HJTMainTabBarVC的View,則KMAnnouncementView會進入白名單待顯示數組中,當HJTMainTabBarVC調用viewwillappear時纔會實際被顯示出來。

一句話介紹白名單

白名單中的key對應的view永遠只會出如今其對應的value中的vc上,即使你在其餘任何VC上調用顯示顯示KMAnnouncementView, KMAnnouncementView也只會出如今其對應的value的vc上。

黑名單模式(功能點5)

黑名單模式包括兩個關鍵內容。

黑名單字典 - blackList
 黑名單HomeVC - blackListHomeVCClassName
複製代碼

黑名單字典位於WKViewManager類中。

字典中key爲ViewController的類名字符串,value是一個數組,裏面應放入對應的從屬於WKBaseView的子類的類名字符串。

例如 黑名單內容爲

@{@"KMBaseViewController",@[@"WKPopBaseView"]};
複製代碼

則代表,WKPopBaseView類(不包含其子類),若是因爲功能塊解耦或者其它緣由,致使WKPopBaseView被展現於KMBaseViewController(不包含其子類)的子視圖上時,WKViewManager會攔截此行爲,將WKPopBaseView實例存入黑名單待顯示數組,當回到黑名單HomeVC時再顯示出來。從而實現了WKPopBaseView必定不會出如今KMBaseViewController的視圖上。

一句話解釋黑名單

黑名單中key對應的vc顯示時,其對應的value中的view必然不會出現,若是被強制出現時,其也不會出現,直到黑名單homeVC的viewwillappear被調用纔會顯示。

功能點6

因爲隊列基於viewcontroller的,因此很簡單隻須要hook viewcontroller的 willappear和diddisappear便可,在willappear裏面找到隊列設置suspended爲NO,在diddisappear裏面suspended爲yes便可

####Demo地址

使用方式

前提:由於內部實現使用了Masonry佈局,因此須要先Pod Masonry三方庫。

步驟1、

下載Demo,找到BaseView文件夾拖入項目。

步驟2、

將文件中的WKViewManagerHeader.h文件加入全局頭文件.pch中。

步驟3、

新建的View繼承自WKPopBaseView,並重寫setInterFace,需首先調用父類的實現

- (void)setInterFace
{
    [super setInterFace];
    //TODO contentview的高度必須設置
    [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self);
        make.centerY.equalTo(self).offset(SCREEN_HEIGHT);
        make.width.height.equalTo(@200);
    }];
}
複製代碼

可自定義出現和消失動畫--------實現updateContentViewConstraint:(BOOL)isShow方法

- (void)updateContentViewConstraint:(BOOL)isShow
{
    [self.contentView mas_updateConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(self).offset(isShow ? 0 : SCREEN_HEIGHT);
    }];
}
複製代碼

還有更多可自定義的效果,可經過頂層基類WKbaseVIew封裝的聲明週期實現。詳情請查看Demo

步驟4、

初始化後,在須要展現的地方調用showInView:isShow:方法便可。

WKTestView * v = [[WKTestView alloc] init];
    v.title = @"This is Test View can not show in HomePage";
    [v showInView:self.view isShow:YES];
複製代碼

交流方式

郵箱357863248@qq.com

相關文章
相關標籤/搜索