UIWindow的使用

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é):

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

參考:
http://www.itdecent.cn/p/f60471a7d935

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、問題背景 最近需求量放緩,想起了以前曾經(jīng)later的小需求,也就是彈出來的AlertView中間的文本框輸入一...
    唐笛_Dylan閱讀 18,806評(píng)論 6 29
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,725評(píng)論 25 709
  • 每一個(gè)IOS程序都有一個(gè)UIWindow,在我們通過模板簡(jiǎn)歷工程的時(shí)候,xcode會(huì)自動(dòng)幫我們生成一個(gè)window...
    jumping鵬閱讀 1,194評(píng)論 0 0
  • UIWindow 簡(jiǎn)介 一個(gè)UIWindow對(duì)象為應(yīng)用程序的用戶界面提供了背景以及重要的事件處理行為。UIWind...
    ripperhe閱讀 23,818評(píng)論 24 58
  • 粉筆劃過流年 留下青春的痕跡 鈴聲劃過時(shí)空 送走回首的記憶 那些同桌的我和你 如今散落各地 那件白色的丑校服 如今...
    綴滿星星的夜空只有我閱讀 510評(píng)論 0 1

友情鏈接更多精彩內(nèi)容