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
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With