APP從后臺模式進入前臺后打開指定頁面
需求:前段時間在開發項目的時候,有一個需求,因為APP的一些信息比較敏感,所以如果用戶在操作APP的過程中按下home鍵退到后臺,超過指定的時間然后再切換到前臺時,需要驗證用戶設置過的指紋或者是手勢來對用戶進行身份驗證
方案一:
當APP進入前臺的時候將
rootViewController
設置為指定的校驗界面.
但是有一個問題:當用戶驗證成功之后呢? 如何回到用戶之前操作過的界面呢? 暫時我沒有好的解決方案, 如果你想到了好的idea,咱們可以一起探討下~
方案二:
當APP進入前臺的時候在當前界面上覆蓋一個
UIWindow
,并設置UIWindowLevel
,當用戶驗證成功之后在將該Window
對象隱藏或者是移除即可
代碼如下:
func applicationDidEnterBackground(_ application: UIApplication) {
leaveTime = Date()
}
func applicationWillEnterForeground(_ application: UIApplication) {
let interval = Int(Date().timeIntervalSince(leaveTime))
//這里假如超過20秒后就讓用戶去驗證
if interval > 20
{
let validateVC = ValidationVC()
//當用戶驗證成功之后重新設置下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
關于 UIWindowLevel
我想多說幾句, UIWindow
在顯示的時候會根據 UIWindowLevel
進行排序的,即 Level
高的將排在最前面.默認是 0
open var windowLevel: UIWindowLevel // default = 0.0
系統為我們定義了三個window
層級,即:
public let UIWindowLevelNormal: UIWindowLevel
public let UIWindowLevelAlert: UIWindowLevel
public let UIWindowLevelStatusBar: UIWindowLevel
我們打印輸出這三個level的值查看下:
STWLog("UIWindowLevelNormal: \(UIWindowLevelNormal)")
STWLog("UIWindowLevelStatusBar: \(UIWindowLevelStatusBar)")
STWLog("UIWindowLevelAlert: \(UIWindowLevelAlert)")
打印結果:
AppDelegate.swift:(43)----------UIWindowLevelNormal: 0.0
AppDelegate.swift:(44)----------UIWindowLevelStatusBar: 1000.0
AppDelegate.swift:(45)----------UIWindowLevelAlert: 2000.0
所以對于他們的級別我們也就一目了然了;
下面我們寫個小Demo測試一下:
@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,設置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,設置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,設置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,設置windowLevel為UIWindowLevelStatusBar
alertLevelWindow2 = UIWindow(frame: CGRect(x: 200, y: 200, width: 100, height: 100))
alertLevelWindow2?.tag = 100000
alertLevelWindow2.backgroundColor = .white
alertLevelWindow2.windowLevel = UIWindowLevelAlert + 10 //隨意設置一個Level
alertLevelWindow2.rootViewController = ViewController()
alertLevelWindow2.makeKeyAndVisible()
print("當前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("此時keyWindow: \(String(describing: UIApplication.shared.keyWindow!.tag))")
for window in UIApplication.shared.windows
{
print("當前window的tag值為:\(window.tag)")
}
})
}
}
運行結果如下圖所示:
打印結果顯示:
當前keyWindow: 100000
此時keyWindow: 10000
當前window的tag值為:0
當前window的tag值為:10
當前window的tag值為:100
當前window的tag值為:1000
當前window的tag值為:10000
什么是 keWindow
? 我們來查看下官方文檔是怎么描述的:
也就是說在 windows
數組中,最近時間調用了 makeKeyAndVisible
方法的就是 keyWindow
了;
總結:
UIWindowLevel
的值不僅僅只有UIWindowLevelNormal
、UIWindowLevelAlert
、UIWindowLevelStatusBar
這三個,可以是自定義的隨意值,哪怕是負數UIWindow
的顯示的確可以通過UIWindowLevel
來區分優先級,所有的window都會被加在界面上,只不過會通過優先級羅列起來,UIWindowLevel
大的在上面顯示,UIWindowLevel
小的在下面顯示。UIWindowLevel
優先級相等的情況下,看誰后實例化了,誰后實例化誰先顯示- 如果將當前
KeyWindow
對象設置為nil
則該對象會從Windows
數組中移除,并且最后實例化的Window對象將成為KeyWindow
,但是依然遵循總結2中的描述,UIWindowLevel
大的在上面顯示,UIWindowLevel
小的在下面顯示。