聲明:文中的圖片雖然是來自掘金的桨踪,也是來自我的掘金號中的圖片老翘,并非抄襲!
一锻离、前言
我們知道铺峭,蘋果在2019年WWDC要求,2020.4月開始上架的 APP 都強制要求使用 LaunchScreen.storyboard汽纠,刪除該 storyboard 卫键,改為各種自定義的廣告啟動頁時代已經(jīng)過去了,那么虱朵,對于各大電商來說莉炉,每年有各種大、中碴犬、小促(越來越頻繁絮宁,是個節(jié)日就促銷),因此服协,活動廣告頁仍舊必不可少绍昂。啟動頁不能刪除,同時還需要廣告頁偿荷,那我們該如何去做呢窘游?
本篇,你將學(xué)到如下知識點:
- 簡單了解 LaunchScreen跳纳;
- 制作啟動頁 + XIB 中設(shè)置約束张峰;
- 雙 UIWindow / 單 UIWindow 切換;
二棒旗、簡單了解 LaunchScreen
LaunchScreen 很簡單,網(wǎng)上有大把的適配方案撩荣。你不能動態(tài)去設(shè)置該 storyboard 铣揉,只能提前在 Xcode 中設(shè)置。因為要考慮到不同機型分辨率的適配問題餐曹,因此逛拱,不建議使用一整張圖 + 約束,除非你添加一整套不同分辨率的圖到工程中台猴,但這樣的話朽合,你的整個 app 包就大了俱两。
個人建議:
- 背景為純色填充;
- 放置小圖 + 約束曹步;
- 放置文字 + 約束宪彩;
出于 Demo 好看,我設(shè)置了一整張圖片 + 兩行文字:
- 圖片采用『Aspect Fill』按比例來充滿整屏(會被截冉不椤)尿孔,所以為何我會建議用純背景色了吧,當(dāng)然筹麸,不怕被截的話活合,那就可以用圖片沒有問題;
- 不同顏色的文字設(shè)置物赶,如下圖:
如何在 XIB 中添加約束白指?
拖線的時候,要先按住『 control 』鍵才行酵紫!
三告嘲、UIWindow 與 廣告頁
在 AppDelegate 中,我們已經(jīng)有了一個 window憨闰,它的 rootViewController 已經(jīng)設(shè)置為我們的 MainTabBarController状蜗,那我們?nèi)绾蜗葐游覀兊膹V告頁,然后再進(jìn)入我們真正的 TabBarController 呢鹉动?
通常轧坎,我們有兩種辦法:
- 單 window,rootViewController 先設(shè)置廣告頁VC泽示,之后再換成 TabBarController缸血;
- 雙 window,rootViewController 分別設(shè)置廣告頁VC 和 TabBarController械筛,只不過捎泻,廣告頁 window 在最上面,然后再切換到 TabBarController 的 window埋哟;
無論哪種方式笆豁,最終的效果都一樣,如下圖:
3.1赤赊、添加廣告頁 VC
// AdvertiseViewController.swift
class AdvertiseViewController: BaseViewController {
// 延遲初始化 timer
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
// 小于等于 0 時闯狱,結(jié)束 timer,并進(jìn)行兩個 rootViewController 的切換
if self!.seconds <= 0 {
self!.terminer()
}
self!.seconds -= 1
}
})
timer.resume()
}
func terminer() {
timer.cancel()
}
}
3.2抛计、單 window 替換法
單 window 替換法如我之前所說哄孤,用戶點擊或者倒計時結(jié)束時,將 window.rootViewController = MainTabBarController() 即可吹截,當(dāng)然瘦陈,還要加點過渡動畫凝危,不然就會顯示太過生硬,實現(xiàn)代碼如下:
// AdvertiseViewController.swift
class AdvertiseViewController: BaseViewController {
......
func terminer() {
timer.cancel()
switchRootController()
}
//
// 一個 window 的情況:只用切換 rootViewController 就行
//
func switchRootController() {
let window = UIApplication.shared.windows.first!
// 過渡動畫:0.5s 淡出
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
// Do Nothing
})
}
}
修改 AppDelegation
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
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 小節(jié)苍匆,再開始本小節(jié)的demo )
修改 AppDelegation
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
// 多個 window:
// 第 1 個用于主app;
// 第 2 個用于顯示廣告頁棚菊;
var windows: [UIWindow]?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// 后一個 window 蓋在前一個之上浸踩,可以通過:
// windows?[下標(biāo)].makeKeyAndVisible() 來切換顯示
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()
// switchRootController()
switchWindow() // 修改這里
}
// 同樣兩種方式可以實現(xiàn):廣告頁 -> 主頁面:
// 1. 兩個 window 來分別控制不同的業(yè)務(wù),然后基于過渡動畫來切換 window统求;
// 2. 一個 window检碗,兩個 vc,分別是 主vc 和 廣告vc码邻,通過修改 window.rootViewController 來完成折剃;
func switchWindow() {
// 第2個 window(廣告窗口)
let window = UIApplication.shared.windows.last!
// 過渡動畫:淡出
UIView.transition(with: window,
duration: 0.5,
options: .transitionCrossDissolve,
animations: {
// 臨時保存 UIView 是否開啟動畫的狀態(tài)(默認(rèn)是開啟)
// 之所以先禁止,是防止存在其它動畫影響了當(dāng)前動畫
// ----------------------------------------
// 設(shè)置了禁止動畫后:
// 1. 當(dāng)前所有正在執(zhí)行動畫的沒有任何影響
// 2. 未執(zhí)行的將不會執(zhí)行動畫
// ----------------------------------------
//
// 因為我們這個回調(diào)是動畫已經(jīng)開始像屋,所以怕犁,并不會被強制停止,
// 最后再恢復(fù) UIView 是否開啟動畫的狀態(tài)即可
let old = UIView.areAnimationsEnabled
UIView.setAnimationsEnabled(false)
window.alpha = 0
UIView.setAnimationsEnabled(old)
}, completion: { _ in
// 切換到主 window,即我們的 MainTabBarController
UIApplication.shared.windows.first?.makeKeyAndVisible()
})
}
無論哪種用法己莺,對于用戶來說奏甫,都是一樣;同樣凌受,最終取決于用單 window 還是雙 window 都由項目(可擴展性)阵子、研發(fā)(技術(shù)、時間胜蛉、能力)等來決定挠进;但總歸,多一種方案多一條路誊册。
四奈梳、總結(jié)
本篇雖然是在介紹如何啟動廣告頁,實際則是讓大家學(xué)習(xí)如何去使用多個 window解虱,以及之間的切換過渡動畫(正所謂授之以魚,不如授之以漁)漆撞。多個 window 看似場景不多殴泰,其實還是有的于宙,比如:視頻類APP,非全屏?xí)r悍汛,頁面滾動捞魁,視頻控件移出到屏幕外不可見時,APP會在當(dāng)前創(chuàng)建一個懸浮在右下角的一個單獨視頻窗口离咐,這就用到了多window 技術(shù)谱俭。
既然是廣告頁,一定會有倒計時的控件不斷時間遞減宵蛀,倒計時結(jié)束后才會進(jìn)入我們的首頁昆著。下一篇,我將介紹本系列的第一個組件:倒計時組件J跆铡(本系列會介紹非常多的常用組件的自定義開發(fā))
歡迎交流凑懂,敬請期待,謝謝梧宫!