UIWindow的使用

作者: Mark_Guan | 来源:发表于2017-10-20 15:05 被阅读268次

    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了;

    总结:

    1. UIWindowLevel 的值不仅仅只有 UIWindowLevelNormalUIWindowLevelAlertUIWindowLevelStatusBar 这三个,可以是自定义的随意值,哪怕是负数
    2. UIWindow 的显示的确可以通过 UIWindowLevel 来区分优先级,所有的window都会被加在界面上,只不过会通过优先级罗列起来,UIWindowLevel 大的在上面显示,UIWindowLevel 小的在下面显示。
    3. UIWindowLevel 优先级相等的情况下,看谁后实例化了,谁后实例化谁先显示
    4. 如果将当前 KeyWindow对象设置为 nil 则该对象会从 Windows数组中移除,并且最后实例化的Window对象将成为 KeyWindow ,但是依然遵循总结2中的描述,UIWindowLevel 大的在上面显示,UIWindowLevel 小的在下面显示。

    参考:
    http://www.jianshu.com/p/f60471a7d935

    相关文章

      网友评论

        本文标题:UIWindow的使用

        本文链接:https://www.haomeiwen.com/subject/korvuxtx.html