2,836
我们知道,苹果在2019年WWDC要求,2020.4月开始上架的 APP 都强制要求使用 LaunchScreen.storyboard,删除该 storyboard ,改为各种自定义的广告启动页时代已经过去了,那么,对于各大电商来说,每年有各种大、中、小促(越来越频繁,是个节日就促销),因此,活动广告页仍旧必不可少。启动页不能删除,同时还需要广告页,那我们该如何去做呢?
本篇,你将学到如下知识点:
简单了解 LaunchScreen;
制作启动页 + XIB 中设置约束;
双 UIWindow / 单 UIWindow 切换;
二、简单了解 LaunchScreen
LaunchScreen 很简单,网上有大把的适配方案。你不能动态去设置该 storyboard ,只能提前在 Xcode 中设置。因为要考虑到不同机型分辨率的适配问题,因此,不建议使用一整张图 + 约束,除非你添加一整套不同分辨率的图到工程中,但这样的话,你的整个 app 包就大了。
个人建议:
背景为纯色填充;
放置小图 + 约束;
放置文字 + 约束;
出于 Demo 好看,我设置了一整张图片 + 两行文字:
图片采用『Aspect Fill』按比例来充满整屏(会被截取),所以为何我会建议用纯背景色了吧,当然,不怕被截的话,那就可以用图片没有问题;
不同颜色的文字设置,如下图:
如何在 XIB 中添加约束?
拖线的时候,要先按住『 control 』键才行!
三、UIWindow 与 广告页
在 AppDelegate 中,我们已经有了一个 window,它的 rootViewController 已经设置为我们的 MainTabBarController,那我们如何先启动我们的广告页,然后再进入我们真正的 TabBarController 呢?
通常,我们有两种办法:
单 window,rootViewController 先设置广告页VC,之后再换成 TabBarController;
双 window,rootViewController 分别设置广告页VC 和 TabBarController,只不过,广告页 window 在最上面,然后再切换到 TabBarController 的 window;
无论哪种方式,最终的效果都一样,如下图:
3.1、添加广告页 VC
class AdvertiseViewController: BaseViewController {
lazy var timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.global())
var seconds = 5
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .kRed
timeCountDown()
func timeCountDown() {
timer.schedule(deadline: .now(), repeating: .seconds(1))
timer.setEventHandler(handler: {
DispatchQueue.main.async { [weak self] in
if self!.seconds <= 0 {
self!.terminer()
self!.seconds -= 1
timer.resume()
func terminer() {
timer.cancel()
3.2、单 window 替换法
单 window 替换法如我之前所说,用户点击或者倒计时结束时,将 window.rootViewController = MainTabBarController() 即可,当然,还要加点过渡动画,不然就会显示太过生硬,实现代码如下:
class AdvertiseViewController: BaseViewController {
......
func terminer() {
timer.cancel()
switchRootController()
func switchRootController() {
let window = UIApplication.shared.windows.first!
UIView.transition(with: window,
duration: 0.5,
options: .transitionCrossDissolve,
animations: {
let old = UIView.areAnimationsEnabled
UIView.setAnimationsEnabled(false)
window.rootViewController = MainTabBarController()
UIView.setAnimationsEnabled(old)
}, completion: { _ in
修改 AppDelegation
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.backgroundColor = .white
window?.rootViewController = AdvertiseViewController()
window?.makeKeyAndVisible()
return true
3.3、双 window 切换法
双 window 顾名思义,就是有两个 window,双 window 不像单 window,是修改 rootViewController,而是通过 api 来控制哪个 window 可见的方式来切换,同样也需要有过渡动画。(先还原代码至 3.1 小节,再开始本小节的demo )
修改 AppDelegation
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var windows: [UIWindow]?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
windows = [
addWindowWithVC(MainTabBarController()),
addWindowWithVC(AdvertiseViewController())
return true
func addWindowWithVC(_ vc: UIViewController) -> UIWindow {
let window = UIWindow.init(frame: UIScreen.main.bounds)
window.backgroundColor = .white
window.rootViewController = vc
window.makeKeyAndVisible()
return window
修改 AdvertiseViewController
class AdvertiseViewController: BaseViewController {
......
func terminer() {
timer.cancel()
switchWindow()
func switchWindow() {
let window = UIApplication.shared.windows.last!
UIView.transition(with: window,
duration: 0.5,
options: .transitionCrossDissolve,
animations: {
let old = UIView.areAnimationsEnabled
UIView.setAnimationsEnabled(false)
window.alpha = 0
UIView.setAnimationsEnabled(old)
}, completion: { _ in
UIApplication.shared.windows.first?.makeKeyAndVisible()
无论哪种用法,对于用户来说,都是一样;同样,最终取决于用单 window 还是双 window 都由项目(可扩展性)、研发(技术、时间、能力)等来决定;但总归,多一种方案多一条路。
本篇虽然是在介绍如何启动广告页,实际则是让大家学习如何去使用多个 window,以及之间的切换过渡动画(正所谓授之以鱼,不如授之以渔)。多个 window 看似场景不多,其实还是有的,比如:视频类APP,非全屏时,页面滚动,视频控件移出到屏幕外不可见时,APP会在当前创建一个悬浮在右下角的一个单独视频窗口,这就用到了多window 技术。
既然是广告页,一定会有倒计时的控件不断时间递减,倒计时结束后才会进入我们的首页。下一篇,我将介绍本系列的第一个组件:倒计时组件!(本系列会介绍非常多的常用组件的自定义开发)
欢迎交流,敬请期待,谢谢!