iOS開屏廣告&彈窗浮層解決方案

開屏廣告做爲app啓動時映入用戶眼簾的第一界面,其重要性不言而喻。 因項目中開屏廣告插件中業務愈來愈多,原來的的方式也已經沒法知足需求。windows

開屏廣告要實現要求:app

1.正常開屏時顯示開屏廣告,且不能顯示狀態欄,若是有開機引導圖則先顯示廣告後顯示引導圖 若是還有其餘的子view 則按順序日後排。佈局

2.app進入後臺一段時間後再次進入前臺也須要顯示廣告,並且廣告不會被 Alert之外的其餘視圖(好比加在keywindow上的彈窗浮層等)擋住。spa

3.從3D touch ,通知欄喚起app時能夠正常顯示廣告。插件

4.喚起app時若是當前的 keywindow是橫向(例如咱們項目裏從 h5頁面喚起 AR看車頁面時,AR會強制旋轉屏幕)的,能夠正常顯示廣告(廣告依然是豎直顯示)。code

5.點擊跳過直接進入app首頁,或者點擊廣告進入廣告落地頁,從廣告頁返回則直接返回到app首頁。orm

在網上也查找了很多資料,其中大部分都是把開屏廣告直接加載到keywindow上。首先前提條件咱們項目 開屏廣告是個單獨的插件,其次咱們項目裏是設置了生命週期

Viewcontroller-based status bar appearance 這個屬性爲YES 的,so 狀態欄的顯示與隱藏須要調用ViewController的隊列

- (BOOL)prefersStatusBarHidden{  
        return YES;//隱藏  
    }

這個方法來控制狀態欄, 若是建立了view加在keywindow上,則狀態欄的狀態則不方便控制,再者當keywindow 強制被旋轉式,要讓view的子視圖也跟着旋轉也是件麻煩事。ip

或者是啓動時把開屏廣告做爲 rootVC,廣告結束以後在切換rootVC爲tabbar 。還有一種是經過切換keyiwindow 的方式實現 。以上兩種方法我也都作了嘗試,能夠知足部分需求,可是都沒法完美的解決以上開屏的需求。

後臺偶然的機會看到 window 的makeKeyAndVisibale方法的註解

- (void)makeKeyAndVisible;

Description

Shows the window and makes it the key window.

This is a convenience method to show the current window and position it in front of all other windows at the same level or lower. If you only want to show the window, change its hidden property to NO.

重點在最後一句: If you only want to show the window, change its hidden property to NO.  。

若是咱們想顯示window just set its hidden屬性爲 NO 便可。 也就是咱們建立的window 默認隱藏的,當我調用 makeKeyAndVisible時,這個window纔會成爲keywindow而且可見。也就是說雖然app中只能有一個keywindow 可是能夠有多個 window同時存在經過控制window的 level來控制顯示的層級。window 的層級有下面幾種:

typedef CGFloat UIWindowLevel; windowlevel 實際上是浮點型的值
UIKIT_EXTERN const UIWindowLevel UIWindowLevelNormal; // 默認值  值爲1000.00
UIKIT_EXTERN const UIWindowLevel UIWindowLevelAlert; //  Alert window所在層級 值爲3000.00
UIKIT_EXTERN const UIWindowLevel UIWindowLevelStatusBar // 狀態欄層級 值 2000.00

程序的keywindow的window level 是默認的 wndowLevelNormal 。

衆所周知開屏廣告實際上是在app啓動以後,蓋在了程序主界面之上 。 既然keywindow 的windowLevel 是normal 的,那麼咱們就能夠在app啓動以後再建立一個window並設置windowLevel 比normal 高,這樣就會蓋住kewindow 顯示廣告了,在廣告流程結束以後再把這個window 隱藏便可。

使用這種方式還有一個最大的優勢,因爲這是一個單獨的window,咱們能夠綁定一個 rootViewController,把開屏廣告的view加在該rootViewController上,viewController有着完整可控的生命週期,而且能夠經過 - (BOOL)prefersStatusBarHidden  方法控制狀態欄的顯示與隱藏, 經過

- (UIInterfaceOrientationMask)supportedInterfaceOrientations 控制屏幕的方向,除此以外,由於他是一個單獨的window,並無加在keywindow上或者是其餘視圖上,只是window level 不一樣,不會對其餘的業務線產生影響,簡直是一舉多得!!!

下面列舉出須要注意的幾點:

1. 廣告的window level 須要設置爲 UIWindowLevelStatusBar - 1 ,不能比 statusBar的windowLevel高,不然立即有廣告又有引導圖的狀況下,點擊廣告跳轉到廣告落地頁(落地頁要顯示狀態欄的),因爲windowLevel比statusBar的高,會致使狀態欄沒法顯示。

2.廣告window的rootVC應該只支持垂直方向,此時rootVC的子view在屏幕旋轉的時候仍會按照垂直方向的frame佈局。

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

3.須要特別注意: 在PLUS系列的手機,因爲PLUS系列的手機在橫屏的時候 手機的整個界面都會跟着旋轉(非PLUS系列手機好像不會)  ,若是PLUS系列手機是在橫屏狀態下啓動的app,此時 viewDidLoad中 view.frame.size.width = MAX(屏幕寬,屏幕高) ,也就是說 view的寬等於手機垂直狀態下的高了,拿7PLUS舉個例子:此時 view.frame = (0,0,736,414) ,在掉用過  - (UIInterfaceOrientationMask)supportedInterfaceOrientations  方法以後,因爲該rootVC只支持垂直方向此時 view的frame纔是正確的,  拿7PLUS舉個例子:此時 view.frame = (0,0,414,736) 。

4.在開平廣告結束時候記得隱藏廣告 window ,並設置爲nil 。

以上就是此次開屏廣告重構肯定下來的方案,既能完美知足各個需求,方便之後擴展需求,又能不對其餘業務線產生影響。

----------------------------------------------------------------

2017-08-09更新

爲了能有更好的通用性,能夠建立一個 Manager類, 相似系統 Alert , 將這些view 放在一個隊列裏去統一管理,當上一個view 的流程結束後,纔去展現下一頁面 。

相關文章
相關標籤/搜索