0

Have been working for a long time trying to find the fix to my crash. Not sure if it's a fundamental design flaw on my part or something that can be fixed easily.

My app has a NavigationController embedded in a TabBarController. When I modally present a view from the root view controller of the NavigationController, it is presented and dismissed without any problem.

However, after i navigate forward in the navigation stack from the root ViewController of the NavigationController pushing other Controllers and then back to the root ViewController, I try the modally presentation again. This time it presents fine but when I dismiss it my app crashes with a EXC_BAD_ACCESS error.

After sometime debugging I found that when the modally presented ViewController is dismissed it is trying to access a ViewController in the navigation Heiarchy that has already been dismissed and thus the crash. Despite the fact that it was presented from the Root ViewController of the Navigation Stack.

It is causing me a lot of grief and wondering if anybody has come across something similar. Any help will be greatly appreciated. Thanks in advance.

Here is the presentation which occurs inside an AlertController Block:

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

I am using an unwind to dismiss the viewController. I have tried dismissing with the following code with the same error:

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

Thanks

Paul Cezanne
  • 8,629
  • 7
  • 59
  • 90
alionthego
  • 8,508
  • 9
  • 52
  • 125
  • Please share the code where you are presenting and dismissing the view controller. – Fawad Masud Jul 12 '15 at 21:47
  • i can see that the presenting view controller of the modal view is the tabbarcontroller. I'm not sure if this is what is causing the problem or how to fix it given that. – alionthego Jul 12 '15 at 21:47
  • Just edited with presenting and dismissing code. Presented from within the block of an AlertController Action. – alionthego Jul 12 '15 at 21:53
  • okay. using Zombie I found the offender. I had declared the second ViewController in the NavigationStack as the delegate for the NavigationController. That's why it was being referenced on the unwind. Just deleting that line took care of the problem! Thanks for those who commented and helped out. – alionthego Jul 12 '15 at 23:55

3 Answers3

0

did you implement the prepareForUnwind function in the presenting view controller? you need that in order for the unwind to work: here is an example in objective C but it's the same concept for swift! This code goes in the presenting view controller:

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

instead of writing code for dismissing the viewcontroller you just need to ctrl + drag from the button you use for dismissing to the exit at the top of the scene and then choose the function "backToHome" from the popup

you should check the connections: https://www.dropbox.com/s/jwpaz1nxvjkautv/Screen%20Shot%202015-07-12%20at%206.16.23%20PM.png?dl=0

Jaimy
  • 227
  • 1
  • 8
  • Yes, I've done the unwind correctly and it works the first time the controller is called from the root view controller. However it is somehow trying to access another view controller the second time it is dismissed. I think there is some conflict being caused by the tab bar controller but can't figure out how to fix the issue. – alionthego Jul 12 '15 at 23:00
0

I recommend you do push segue and make your own protocol, that way you can navigate back to any viewcontroller. For your example, the pushed viewcontroller code I wrote is :

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!)];
    }
}

in the presenting view controller code is:

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)     
}
Jaimy
  • 227
  • 1
  • 8
  • Thank you. I wanted to keep the modal presentation. It turns out the problem was declaring a view down the line as the navigation controller delegate. Thank's to Zombie I managed to isolate that. – alionthego Jul 12 '15 at 23:58
0

I found the problem. I had declared the second view in the NavigationController Hierarchy as the delegate for the NavigationController. That's why it was being referenced. When I removed that line of code the problem went away. Thanks very much for all who commented and helped out.

alionthego
  • 8,508
  • 9
  • 52
  • 125