Swift尝试呈现UIAlertController,但其视图不在窗口层次结构中(在TWTRShareEmailViewController之后呈现)

14

我在我的应用注册流程中使用 Twitter 登录,并要求用户提供电子邮件。一旦获取到电子邮件,我希望显示一个 UIAlertController。

这是我的代码:

func askForTWMail(){
    if (Twitter.sharedInstance().session() != nil) {
        let shareMailVC=TWTRShareEmailViewController(completion: {(mail:String!, error:NSError!) in
            if (mail != nil) {
                print("GOT MAIL: \(mail)")
                self.gotMail()
            }else{
                print("MAIL VC ERROR: \(error)")
            }
        })
        println("PRESENT MAIL VC")
        self.presentViewController(shareMailVC, animated: true, completion: nil)
    }else{
        println("User not logged in")
    }
}

func gotMail(){
    var alertController=UIAlertController(title: "Some title", message: "Some message", preferredStyle: UIAlertControllerStyle.Alert)
    var okAction=UIAlertAction(title:"Yes", style: UIAlertActionStyle.Default) {
    UIAlertAction in
    //some action
    }
    var cancelAction=UIAlertAction(title:"No", style: UIAlertActionStyle.Cancel){
    UIAlertAction in
    //some action
    }
    alertController.addAction(okAction)
    alertController.addAction(cancelAction)
    self.presentViewController(alertController, animated: true, completion: nil)                
}

但是我遇到了这个错误(我想是因为TWTRShareEmailViewController没有被取消):

警告:试图在不在窗口层级结构中的xViewController上呈现UIALertController!

你有什么建议吗?我该如何知道TWTRShareEmailViewController何时取消以继续注册过程并能够展示我的UIAlertController?我不知道与TWTRShareEmailViewController相关的委托方法。

任何帮助都将不胜感激。谢谢。

4个回答

34

在这里找到了一个解决方案我可能做错了,但如果没有,那可能是苹果的问题。解决方法是延迟呈现UIAlertController

dispatch_async(dispatch_get_main_queue(), ^{
    self.presentViewController(alertController, animated: true, completion: nil)
})

编辑:我找到了另一个解决方法(我不再使用我在这里提到的解决方案)。我不得不改变这个,因为Twitter登录也破坏了我在视图控制器之间的过渡。

现在我调用一个特定的UIViewController(我叫它类似TWLoginVC的东西),在那里我做所有的Twitter登录和其他事情。视图只是黑色的,所以用户看不到进程实际上是在另一个VC中完成的(他只需要选择他想要登录的Twitter用户)。我猜你也可以把背景设为透明,更加隐形。

当我调用这个视图控制器并解除它时,过渡不会应用于它,我就不再遇到任何问题了。


编辑 Swift更新:

DispatchQueue.main.async{
     self.present(alertController, animated: true, completion: nil)
}

你找到了这个问题的更好解决方案吗?我也在使用dispatch_async。 - Ignacio Chiazzo
正如我在我的编辑回复中解释的那样,我有一个专门用于Twitter的VC。因此,当用户想要使用Twitter登录时,我会以模态方式呈现我的“TWLoginVC”,在那里完成所有操作(例如,在某些情况下避免奇怪的行为,使用特殊的VC之间的转换)。但是,我稍微改了一下代码,不再需要呈现UIAlertController了。所以很抱歉,我没有更好的解决方案 :/ - Marie Dm
1
使用新的TwitterKit(我刚刚更新为v 2.0.2),请求用户电子邮件的方式已更改。可以在Twitter文档中找到详细说明:https://docs.fabric.io/ios/twitter/request-user-email-address.html。 - Marie Dm

5

以下是在Xcode 8环境下,根据Marie Dm的回答更新过的Swift 3代码。

DispatchQueue.main.sync {
     self.present(alertController, animated: true, completion: nil)
}

-1
如果 DispatchQueue.main.sync 导致崩溃,请尝试使用 DispatchQueue.main.async。在从 contactPicker() 返回时,async 对我的问题起了作用。

-1

延迟呈现视图控制器解决了我的问题,也让我度过了美好的一天 :D

Swift 4.0:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { 
    //present your view controller her
    self.presentViewController(alertController, animated: true, completion: nil)
}

像这样添加基于时间的代码(然后是基于设备的)从来不是一个好主意。 - Sat Thiru

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接