APP從后臺(tái)模式進(jìn)入前臺(tái)后打開指定頁(yè)面
需求:前段時(shí)間在開發(fā)項(xiàng)目的時(shí)候,有一個(gè)需求,因?yàn)锳PP的一些信息比較敏感,所以如果用戶在操作APP的過程中按下home鍵退到后臺(tái),超過指定的時(shí)間然后再切換到前臺(tái)時(shí),需要驗(yàn)證用戶設(shè)置過的指紋或者是手勢(shì)來對(duì)用戶進(jìn)行身份驗(yàn)證
方案一:
當(dāng)APP進(jìn)入前臺(tái)的時(shí)候?qū)?
rootViewController設(shè)置為指定的校驗(yàn)界面.
但是有一個(gè)問題:當(dāng)用戶驗(yàn)證成功之后呢? 如何回到用戶之前操作過的界面呢? 暫時(shí)我沒有好的解決方案, 如果你想到了好的idea,咱們可以一起探討下~
方案二:
當(dāng)APP進(jìn)入前臺(tái)的時(shí)候在當(dāng)前界面上覆蓋一個(gè)
UIWindow,并設(shè)置UIWindowLevel,當(dāng)用戶驗(yàn)證成功之后在將該Window對(duì)象隱藏或者是移除即可
代碼如下:
func applicationDidEnterBackground(_ application: UIApplication) {
leaveTime = Date()
}
func applicationWillEnterForeground(_ application: UIApplication) {
let interval = Int(Date().timeIntervalSince(leaveTime))
//這里假如超過20秒后就讓用戶去驗(yàn)證
if interval > 20
{
let validateVC = ValidationVC()
//當(dāng)用戶驗(yàn)證成功之后重新設(shè)置下windowLevel即可;
validateVC.closeCallBack = {
self.gestureWindow?.windowLevel = -1
}
let window = UIWindow(frame: UIScreen.main.bounds)
window.windowLevel = UIWindowLevelAlert + 1
window.rootViewController = validateVC
window.makeKeyAndVisible()
self.gestureWindow = window
}
}
UIWindowLevel
關(guān)于 UIWindowLevel 我想多說幾句, UIWindow 在顯示的時(shí)候會(huì)根據(jù) UIWindowLevel 進(jìn)行排序的,即 Level 高的將排在最前面.默認(rèn)是 0
open var windowLevel: UIWindowLevel // default = 0.0
系統(tǒng)為我們定義了三個(gè)window層級(jí),即:
public let UIWindowLevelNormal: UIWindowLevel
public let UIWindowLevelAlert: UIWindowLevel
public let UIWindowLevelStatusBar: UIWindowLevel
我們打印輸出這三個(gè)level的值查看下:
STWLog("UIWindowLevelNormal: \(UIWindowLevelNormal)")
STWLog("UIWindowLevelStatusBar: \(UIWindowLevelStatusBar)")
STWLog("UIWindowLevelAlert: \(UIWindowLevelAlert)")
打印結(jié)果:
AppDelegate.swift:(43)----------UIWindowLevelNormal: 0.0
AppDelegate.swift:(44)----------UIWindowLevelStatusBar: 1000.0
AppDelegate.swift:(45)----------UIWindowLevelAlert: 2000.0
所以對(duì)于他們的級(jí)別我們也就一目了然了;
下面我們寫個(gè)小Demo測(cè)試一下:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var normalWindow: UIWindow!
var alertLevelWindow: UIWindow!
var statusLevelWindow: UIWindow!
var alertLevelWindow2: UIWindow!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
window?.tag = 10
window?.backgroundColor = .red
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
//自定義Window,設(shè)置windowLevel為UIWindowLevelNormal
normalWindow = UIWindow(frame: CGRect(x: 50, y: 50, width: 100, height: 100))
normalWindow?.tag = 100
normalWindow.backgroundColor = .green
normalWindow.windowLevel = UIWindowLevelNormal
normalWindow.rootViewController = ViewController()
normalWindow.makeKeyAndVisible()
//自定義Window,設(shè)置windowLevel為UIWindowLevelNormal
alertLevelWindow = UIWindow(frame: CGRect(x: 150, y: 150, width: 100, height: 100))
alertLevelWindow?.tag = 10000
alertLevelWindow.backgroundColor = .blue
alertLevelWindow.windowLevel = UIWindowLevelAlert
alertLevelWindow.rootViewController = ViewController()
alertLevelWindow.makeKeyAndVisible()
//自定義Window,設(shè)置windowLevel為UIWindowLevelStatusBar
statusLevelWindow = UIWindow(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
statusLevelWindow?.tag = 1000
statusLevelWindow.backgroundColor = .yellow
statusLevelWindow.windowLevel = UIWindowLevelStatusBar
statusLevelWindow.rootViewController = ViewController()
statusLevelWindow.makeKeyAndVisible()
//自定義Window,設(shè)置windowLevel為UIWindowLevelStatusBar
alertLevelWindow2 = UIWindow(frame: CGRect(x: 200, y: 200, width: 100, height: 100))
alertLevelWindow2?.tag = 100000
alertLevelWindow2.backgroundColor = .white
alertLevelWindow2.windowLevel = UIWindowLevelAlert + 10 //隨意設(shè)置一個(gè)Level
alertLevelWindow2.rootViewController = ViewController()
alertLevelWindow2.makeKeyAndVisible()
print("當(dāng)前keyWindow: \(String(describing: UIApplication.shared.keyWindow!.tag))")
return true
}
func applicationWillEnterForeground(_ application: UIApplication) {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2.0, execute: {
self.alertLevelWindow2 = nil
})
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 4.0, execute: {
print("此時(shí)keyWindow: \(String(describing: UIApplication.shared.keyWindow!.tag))")
for window in UIApplication.shared.windows
{
print("當(dāng)前window的tag值為:\(window.tag)")
}
})
}
}
運(yùn)行結(jié)果如下圖所示:

打印結(jié)果顯示:
當(dāng)前keyWindow: 100000
此時(shí)keyWindow: 10000
當(dāng)前window的tag值為:0
當(dāng)前window的tag值為:10
當(dāng)前window的tag值為:100
當(dāng)前window的tag值為:1000
當(dāng)前window的tag值為:10000
什么是 keWindow ? 我們來查看下官方文檔是怎么描述的:

也就是說在 windows 數(shù)組中,最近時(shí)間調(diào)用了 makeKeyAndVisible 方法的就是 keyWindow了;
總結(jié):
UIWindowLevel的值不僅僅只有UIWindowLevelNormal、UIWindowLevelAlert、UIWindowLevelStatusBar這三個(gè),可以是自定義的隨意值,哪怕是負(fù)數(shù)UIWindow的顯示的確可以通過UIWindowLevel來區(qū)分優(yōu)先級(jí),所有的window都會(huì)被加在界面上,只不過會(huì)通過優(yōu)先級(jí)羅列起來,UIWindowLevel大的在上面顯示,UIWindowLevel小的在下面顯示。UIWindowLevel優(yōu)先級(jí)相等的情況下,看誰后實(shí)例化了,誰后實(shí)例化誰先顯示- 如果將當(dāng)前
KeyWindow對(duì)象設(shè)置為nil則該對(duì)象會(huì)從Windows數(shù)組中移除,并且最后實(shí)例化的Window對(duì)象將成為KeyWindow,但是依然遵循總結(jié)2中的描述,UIWindowLevel大的在上面顯示,UIWindowLevel小的在下面顯示。