iOS开屏广告&弹窗浮层解决方案

开屏广告作为app启动时映入用户眼帘的第一界面,其重要性不言而喻。 因项目中开屏广告插件中业务越来越多,原来的的方式也已经无法满足需求。

开屏广告要实现要求:

1.正常开屏时显示开屏广告,且不能显示状态栏,如果有开机引导图则先显示广告后显示引导图 如果还有其他的子view 则按顺序往后排。

2.app进入后台一段时间后再次进入前台也需要显示广告,而且广告不会被 Alert以外的其他视图(比如加在keywindow上的弹窗浮层等)挡住。

3.从3D touch ,通知栏唤起app时可以正常显示广告。

4.唤起app时如果当前的 keywindow是横向(例如我们项目里从 h5页面唤起 AR看车页面时,AR会强制旋转屏幕)的,可以正常显示广告(广告依然是竖直显示)。

5.点击跳过直接进入app首页,或者点击广告进入广告落地页,从广告页返回则直接返回到app首页。

在网上也查找了不少资料,其中大部分都是把开屏广告直接加载到keywindow上。首先前提条件我们项目 开屏广告是个单独的插件,其次我们项目里是设置了

Viewcontroller-based status bar appearance 这个属性为YES 的,so 状态栏的显示与隐藏需要调用ViewController的

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

这个方法来控制状态栏, 如果创建了view加在keywindow上,则状态栏的状态则不方便控制,再者当keywindow 强制被旋转式,要让view的子视图也跟着旋转也是件麻烦事。

或者是启动时把开屏广告作为 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 的流程结束后,才去展示下一页面 。

 

转载于:https://my.oschina.net/zhxx/blog/910836

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值