将模态视图控制器解散回嵌入在 TabBarController 中的导航控制器堆栈导致崩溃

Posted

技术标签:

【中文标题】将模态视图控制器解散回嵌入在 TabBarController 中的导航控制器堆栈导致崩溃【英文标题】:Dismissing a Modal ViewController back to a Navigation Controller Stack imbedded in a TabBarController causing crash 【发布时间】:2015-07-12 21:45:04 【问题描述】:

已经工作了很长时间,试图找到解决我崩溃的方法。不确定这是我的基本设计缺陷还是可以轻松修复的东西。

我的应用在 TabBarController 中嵌入了 NavigationController。当我从 NavigationController 的根视图控制器模态呈现视图时,它会毫无问题地呈现和关闭。

但是,在我从 NavigationController 的根 ViewController 向前导航到导航堆栈中并推送其他控制器然后返回到根 ViewController 之后,我再次尝试模态演示。这次它显示得很好,但是当我关闭它时,我的应用程序崩溃并出现 EXC_BAD_ACCESS 错误。

经过一段时间的调试,我发现当模态呈现的 ViewController 被解除时,它试图访问导航 Heiarchy 中已经被解除的 ViewController 并因此崩溃。尽管它是从导航堆栈的根视图控制器中呈现的。

这让我很伤心,想知道是否有人遇到过类似的事情。任何帮助将不胜感激。提前致谢。

这是发生在 AlertController 块中的演示:

 let createNewMemoAction = UIAlertAction(title: "Create New Memo", style: .Default)  (action: UIAlertAction!) -> Void in
     self.performSegueWithIdentifier("Segue To Create New Memo", sender: nil)
 

我正在使用展开来关闭 viewController。我尝试使用以下代码解除相同的错误:

 @IBAction func cancelButtonPressed(sender: UIBarButtonItem) 
     dismissViewControllerAnimated(true, completion: nil)
 

谢谢

【问题讨论】:

请分享您展示和关闭视图控制器的代码。 我可以看到模态视图的呈现视图控制器是tabbarcontroller。我不确定这是否是导致问题的原因或鉴于此问题如何解决。 刚刚编辑了呈现和关闭代码。从 AlertController Action 的块中呈现。 好的。使用 Zombie 我找到了罪犯。我已将 NavigationStack 中的第二个 ViewController 声明为 NavigationController 的委托。这就是为什么它在展开时被引用。只需删除该行即可解决问题!感谢那些评论和帮助的人。 【参考方案1】:

您是否在呈现视图控制器中实现了 prepareForUnwind 函数?您需要它才能使展开工作:这是目标 C 中的一个示例,但它与 swift 的概念相同! 此代码进入呈现视图控制器:

@IBAction func backToHome(segue:UIStoryboardSegue) 
    // code is not necessary here!

无需编写关闭视图控制器的代码,您只需从用于关闭的按钮 ctrl + 拖动到场景顶部的退出,然后从弹出窗口中选择功能“backToHome”

您应该检查连接: https://www.dropbox.com/s/jwpaz1nxvjkautv/Screen%20Shot%202015-07-12%20at%206.16.23%20PM.png?dl=0

【讨论】:

是的,我已经正确地完成了展开,并且它在第一次从根视图控制器调用控制器时工作。然而,它以某种方式在第二次被解雇时试图访问另一个视图控制器。我认为标签栏控制器引起了一些冲突,但无法弄清楚如何解决该问题。【参考方案2】:

我建议您执行 push segue 并制定自己的协议,这样您就可以导航回任何视图控制器。对于您的示例,我编写的推送视图控制器代码是:

import UIKit
protocol BoxMessageDelegate    
    func userDidType(controller: TextAddition, sendsmessage: String) ->  Void;    



class TextAddition: UIViewController 

    var delegate: BoxMessageDelegate?;
    var message: String?;

    @IBOutlet weak var textMsgField: UITextField!

    @IBAction func `return`(sender: UIButton) 
        self.message = self.textMsgField.text;
        [self.delegate!.userDidType(self, sendsmessage: message!)];
    

在呈现视图控制器代码是:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
    if (segue.identifier == "MessageView") 
        var controller = segue.destinationViewController as! TextAddition              
        controller.delegate = self
    


/*
conforming to protocol here
*/
func userDidType(controller: TextAddition, sendsmessage: String) 
    mySquare.text = sendsmessage;
    self.navigationController?.popToViewController(self, animated: true)     

【讨论】:

谢谢。我想保留模态演示。事实证明,问题在于将视图声明为导航控制器委托。感谢 Zombie,我设法将其隔离。【参考方案3】:

我发现了问题。我已将 NavigationController 层次结构中的第二个视图声明为 NavigationController 的委托。这就是它被引用的原因。当我删除那行代码时,问题就消失了。非常感谢所有评论和帮助的人。

【讨论】:

以上是关于将模态视图控制器解散回嵌入在 TabBarController 中的导航控制器堆栈导致崩溃的主要内容,如果未能解决你的问题,请参考以下文章

iPad 模态控制器在旋转后被解散

以编程方式将导航控制器嵌入模态视图控制器

以模态方式将嵌入在导航控制器中的视图控制器与标签栏控制器分开

将属性从模态视图控制器传递给父级

将 NSMutableArray 从模态视图控制器传递到父视图

将模态呈现的视图控制器关闭到不同的底层视图控制器