Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift – self.navigationController becomes nil after transition

I'm experiencing a very strange error in my app, between two views, self.navigationController is becoming nil

I have a few view controllers: MainViewController, SecondViewController PastSessionsViewController, JournalViewController. I use JournalViewController for two purposes, to save a new entry into CoreData or to edit an older one. The details aren't really relevant to this error.

The error occurs when I try to pop JournalViewController off the stack and return to MainViewController but only when JournalViewController is in "edit" mode, not when it's in "save a new entry mode"

Any idea 1) why this is happening and 2) how to correctly address it so I can return to PastSessionsViewController when coming back from JournalViewController in edit mode?

Here's some code to make things concrete.

In AppDelegate.swift (inside of didFinishLaunchingWithOptions):

navController = UINavigationController()

navController!.navigationBarHidden = true
var viewController = MainViewController()
navController!.pushViewController(viewController, animated: false)

window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.backgroundColor = UIColor.whiteColor()
window?.rootViewController = navController
window?.makeKeyAndVisible()

In MainViewController:

func goToPastSessions(sender: UIButton) {
    let pastSessionsVC = PastSessionsViewController()
    self.navigationController?.pushViewController(pastSessionsVC, animated: true)
}

func goToWriteJournalEntry(sender: UIButton) {
    let journalVC = JournalViewController(label: "Record your thoughts")
    self.navigationController?.pushViewController(journalVC, animated: true)
}

In PastSessionsViewController:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let editJournalVC = JournalViewController(label: "Edit your thoughts")

    let indexPath = tableView.indexPathForSelectedRow()
    let location = indexPath?.row
    let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as! EntryCell

    if let objects = pastSessionsDataSource.coreDataReturn {
        if let location = location {
            editJournalVC.journalEntryCoreDataLocation = location
            editJournalVC.editEntry = true
            editJournalVC.journalEntryToEdit = objects[location].journalEntry
        }
    }

    self.navigationController?.presentViewController(editJournalVC, animated: true, completion: nil)
}

And finally, in JournalViewController:

func doneJournalEntry(sender: UIButton) {
    journalEntryTextArea?.resignFirstResponder()
    var entry = journalEntryTextArea?.text

    if let entry = entry {
        let appDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
        let managedObjectContext = appDelegate.managedObjectContext!
        let request = NSFetchRequest(entityName: "Session")
        var error: NSError?

        // new entry
        if journalEntryText == "Record your thoughts" {
            let result = managedObjectContext.executeFetchRequest(request, error: &error)

            if let objects = result as? [Session] {
                if let lastTime = objects.last {
                    lastTime.journalEntry = entry
                }
            }
        } else {
            // existing entry
            let sortDescriptor = NSSortDescriptor(key: "date", ascending: false)
            request.sortDescriptors = [sortDescriptor]

            let result = managedObjectContext.executeFetchRequest(request, error: &error)
            if let objects = result as? [Session] {
                var location = journalEntryCoreDataLocation

                var object = objects[location!]
                object.journalEntry = entry
            }
        }

        if !managedObjectContext.save(&error) {
            println("save failed: \(error?.localizedDescription)")
        }
    }

   // in "edit" mode, self.navigationController is `nil` and this fails
   // in "record a new entry" mode, it's not nil and works fine
    self.navigationController?.popViewControllerAnimated(true)
}

func cancelEntryOrEditAndReturn(sender: UIButton) {
    self.journalEntryTextArea?.resignFirstResponder()

   // in "edit" mode, self.navigationController is `nil` and this fails
   // in "record a new entry" mode, it's not nil and works fine
    self.navigationController?.popViewControllerAnimated(true)
}

Thanks for taking a look

like image 955
Zack Shapiro Avatar asked Mar 15 '23 14:03

Zack Shapiro


1 Answers

You should push editJournalVC instead of presenting if you want it to be in same navigation stack. Because when you present controller its no longer in same navigation stack. Also if you are presenting it, you should dismiss it not pop. So if you want to present controller you should use

self.dismissViewControllerAnimated(true, completion: nil)

instead

self.navigationController?.popViewControllerAnimated(true)
like image 179
sanjana Avatar answered Mar 24 '23 19:03

sanjana