首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >警告:尝试在视图不在窗口层次结构中的<x.x:x>上显示

警告:尝试在视图不在窗口层次结构中的<x.x:x>上显示
EN

Stack Overflow用户
提问于 2016-03-02 05:55:54
回答 2查看 596关注 0票数 0

我是Swift的新手,但我正在创建一个应用程序,需要在一定时间后输入Touch-ID或PIN。我正在检查来自AppDelegate.swift的计时器,看看它是否已经过期,如果它已经过期,我将调用我的"BaseTableViewController“,它包含我的函数authenticateUser。我再一次从我的AppDelegate.swift文件中调用它,方法是创建一个BaseTableViewController var baseTableVC = BaseTableViewController()的实例,并在计时器过期时调用self.baseTableVC.authenticateUser()

无论如何,我得到了:警告:Attempt to present <UIAlertController: 0x7fed5ae1dcf0> on <admin.BaseViewController: 0x7fed5ad279d0> whose view is not in the window hierarchy!

提前感谢您的帮助!

代码语言:javascript
复制
    func showPasswordAlert(){
    let alertController = UIAlertController(title: "Touch ID Password", message: "Please enter your password", preferredStyle: .Alert)
    let defaultAction = UIAlertAction(title: "OK", style: .Cancel) {(action) -> Void in
        if let textField = alertController.textFields?.first as UITextField?{
            if textField.text == "hello" {
                print("Authentication successfull!")
            }
            else{
                self.showPasswordAlert()
            }
        }

    }
    alertController.addAction(defaultAction)
    alertController.addTextFieldWithConfigurationHandler{(textField) -> Void in
        textField.placeholder = "Password"
        textField.secureTextEntry = true

    }
    presentViewController(alertController, animated: true, completion: nil)

}

func authenticateUser(){
    let context = LAContext()
    var error: NSError?
    let reasonString = "Authentication is required for Admin!"
    context.localizedFallbackTitle = "Enter your PIN Code"

    if context.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &error){
        context.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: reasonString, reply: {(success, policyError) ->Void in
            if success{
                print("Authentication successful!")
            }
            else{
                switch policyError!.code{
                case LAError.SystemCancel.rawValue:
                    print("Authentication was cancelled by the system!")
                case LAError.UserCancel.rawValue:
                    NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
                        self.showPasswordAlert()

                    })
                    print("Authentication was cancelled by the user!")
                case LAError.UserFallback.rawValue:
                    print("User selected to enter password.")
                    NSOperationQueue.mainQueue().addOperationWithBlock({() -> Void in
                        self.showPasswordAlert()
                    })
                default:
                    print("Authentication failed!")
                    NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
                        self.showPasswordAlert()
                    })
                }
            }
        })
    }
    else{
        print(error?.localizedDescription)
        NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
            self.showPasswordAlert()
        })
    }

var baseTableVC = BaseTableViewController()

func applicationWillEnterForeground(application: UIApplication) {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    let logInStatus = NSUserDefaults.standardUserDefaults()
    let currentTime = NSDate().timeIntervalSince1970
    let roundCurrentTime = (round(currentTime))
    // Pin expire limit
    let pinExpLimit: Double = 30
    // Set the exact time of expire for pin
    let pinExpDate = (currentTime + pinExpLimit)
    let newPinExpDate = (round(pinExpDate))
    if (logInStatus.doubleForKey("expPinTime") <= roundCurrentTime) {
        self.baseTableVC.authenticateUser()
        print("AppDelegate Pin Exp Time")
        print(logInStatus.doubleForKey("expPinTime"))
        //print(newPinExpDate)
        print("AppDelegate Current Time")
        print(roundCurrentTime)
        logInStatus.setDouble(newPinExpDate, forKey: "expPinTime")
        NSUserDefaults.standardUserDefaults().synchronize()

    }
}
EN

回答 2

Stack Overflow用户

发布于 2016-03-02 06:19:31

我怀疑您只是创建了BaseTableViewController的一个实例,但是在呈现UIAlertController的实例之前,您没有将它的视图添加到视图层次结构中。

如果self.baseTableVC是应用程序的根视图控制器,那么像这样的调用

代码语言:javascript
复制
baseTableVC.presentViewController(instanceOfUIAlertController, animated: true, completion: yourCompletionBlock)

应该从AppDelegate内部工作。如果self.baseTableVC不是根视图控制器,请确保在应用的根VC上调用前面的命令

代码语言:javascript
复制
window.rootViewController.presentViewController(instanceOfUIAlertController, animated: true, completion: yourCompletionBlock)

或者确保在视图层次结构中嵌入self.baseTableVC的视图,然后调用

代码语言:javascript
复制
baseTableVC.presentViewController(instanceOfUIAlertController, animated: true, completion: yourCompletionBlock)

顺便说一句,如果你的提醒必须在应用程序中的任何地方显示,那么你的方法是可以的。相反,如果您的警报必须仅从特定屏幕显示,我将从应用程序委托中删除计时器逻辑,并将其移动到呈现视图控制器中。这将使您的应用程序委托远离不必要的代码,并将控制逻辑限制在正确的位置:呈现视图控制器

票数 1
EN

Stack Overflow用户

发布于 2016-03-02 08:55:34

你不能仅仅通过调用默认的构造函数来创建视图控制器的实例,使用故事板。如果我错了,请纠正我

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35734359

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档