在iOS中呈现锁定屏幕的最佳方法是什么?

时间:2018-07-10 07:36:42

标签: ios swift appdelegate

我想知道在iOS(swift)中显示锁屏的最佳方法。

ex)如果用户按下主屏幕按钮或接听电话,我想在用户重新输入应用程序时显示锁定屏幕。

所以,我尝试过这种方式。

func applicationWillResignActive(_ application: UIApplication) {
    guard let passcodeManageView = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "passcodeManageView") as? PasscodeManageViewController else { return }

    if let window = self.window, let rootViewController = window.rootViewController {
        var currentController = rootViewController
        while let presentController = currentController.presentedViewController {
            currentController = presentController
        }
        currentController.present(passcodeManageView, animated: true, completion: nil)
    }
}

实际上,它运作良好。

但是,如果显示警报窗口,则它无法正常工作。

我该如何解决? (对不起,我的英文。)

1 个答案:

答案 0 :(得分:0)

在这些情况下,警报视图始终是一个问题。一种快速的解决方案可能是检查是否显示警报视图并将其关闭。我玩过以下游戏:

    func showOverlayController(currentController: UIViewController) {
    currentController.present(OverlayViewController(), animated: true, completion: nil)
}

if let window = UIApplication.shared.keyWindow, let rootViewController = window.rootViewController {
    var currentController = rootViewController
    while let presentController = currentController.presentedViewController {
        guard presentController as? UIAlertController == nil else {
            presentController.dismiss(animated: false) {
                showOverlayController(currentController: currentController)
            }
            return
        }
        currentController = presentController
    }
    showOverlayController(currentController: currentController)
}

搁置动画,这一切似乎仍然很糟糕,因为我怀疑导航控制器或标签栏控制器(或任何其他类型的内容视图控制器)中的视图控制器是否会显示警报视图,此问题将再次显示出来。您可以使用与找到顶级控制器相同的逻辑来始终在顶级控制器上显示警报视图以解决此问题。

因此,我转到了另一种方式,我宁愿更改根视图控制器,也不要呈现叠加层。所以我尝试了以下方法:

static var currentOverlay: (overlay: OverlayViewController, stashedController: UIViewController)?
static func showOverlay() {
    guard currentOverlay == nil else { return }
    guard let currentController = UIApplication.shared.keyWindow?.rootViewController else { return }

    let overlay: (overlay: OverlayViewController, stashedController: UIViewController) = (overlay: OverlayViewController(), stashedController: currentController)
    self.currentOverlay = overlay

    UIApplication.shared.keyWindow?.rootViewController = overlay.overlay
}
static func hideOverlay() {
    guard let currentOverlay = currentOverlay else { return }
    self.currentOverlay = nil
    UIApplication.shared.keyWindow?.rootViewController = currentOverlay.stashedController
}

它很好用...直到再次显示警报视图。因此,经过一番检查,我发现在出现警报视图的情况下,您的应用程序具有多个窗口。警报会在当前窗口之上创建一个新窗口,这是有道理的,但是我不确定有人会怎么认为它会很直观,或者以任何可能的方式表明您正在显示警报视图。然后,我会期望像UIApplication.shared.showAlert(alert)这样的东西,但让我们把这种愚蠢置于一旁。

我在这里看到的唯一实际解决方案是为对话框添加一个新窗口。为此,您可以在网上浏览。以下内容似乎对我有用:

static var currentOverlayWindow: (overlay: OverlayViewController, window: UIWindow, previousWindow: UIWindow)?
static func showOverlay() {
    guard currentOverlay == nil else { return }
    guard let currentWindow = UIApplication.shared.keyWindow else { return }

    let overlay: (overlay: OverlayViewController, window: UIWindow, previousWindow: UIWindow) = (overlay: OverlayViewController(), window: UIWindow(frame: currentWindow.bounds), previousWindow: currentWindow)
    self.currentOverlayWindow = overlay

    overlay.window.backgroundColor = UIColor.black
    overlay.window.rootViewController = overlay.overlay
    overlay.window.windowLevel = UIWindowLevelAlert + 1
    overlay.window.makeKeyAndVisible()

}
static func hideOverlay() {
    guard let currentOverlayWindow = currentOverlayWindow else { return }
    self.currentOverlay = nil
    currentOverlayWindow.window.isHidden = true
    currentOverlayWindow.previousWindow.makeKeyAndVisible()
}

只需填补空白即可。我用作叠加视图控制器的内容:

class OverlayViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let button = UIButton(frame: CGRect(x: 12.0, y: 100.0, width: 150.0, height: 55.0))
        button.setTitle("Dismiss", for: .normal)
        view.addSubview(button)
        button.addTarget(self, action: #selector(onButton), for: .touchUpInside)
    }
    @objc private func onButton() {
        AppDelegate.hideOverlay()
//        self.dismiss(animated: true, completion: nil)
    }

}