Steve PM Steve PM - 4 months ago 11
Swift Question

Second segue from TableViewController creating SIGABRT error relating to the first

I have created a NoteBook application within a larger app. I have all the functionality working including a segue to an Add Note page which triggers programatically from clicking a note (to edit it) or a + barButtonItem.

I need a second segue to send the user back to the home page of the app, but every way I seem to try it conflicts with the existing segue I have in place.

Can anyone suggest a way to get the second segue to work. They both have different identifiers which I am referencing in the methods. Its just the goHome segue that will not work...

class NoteBookViewController: UITableViewController, NoteViewDelegate {

func didUpdateNoteWithTitle(newTitle: String, andBody newBody: String) {
self.noteBookEntries[self.selectedIndex] ["title"] = newTitle
self.noteBookEntries[self.selectedIndex] ["body"] = newBody

self.tableView.reloadData()

saveNotesArray()
}

var noteBookEntries = [[String:String]] ()

@IBAction func newNote() {

var newNote = ["title" : "", "body" : ""]
noteBookEntries.insert(newNote, at: 0)

self.selectedIndex = 0

self.tableView.reloadData()

saveNotesArray()

performSegue(withIdentifier: "editNoteBookSegue", sender: nil)
}

var selectedIndex = -1

func saveNotesArray() {

UserDefaults.standard.set(noteBookEntries, forKey: "notes")
UserDefaults.standard.synchronize()
}

override func viewDidLoad() {
super.viewDidLoad()

if let newNote = UserDefaults.standard.array(forKey: "notes") as? [[String:String]] {
noteBookEntries = newNote
}

self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.reply, target: self, action: #selector(NoteBookViewController.navigateToNextViewController))

}

func navigateToNextViewController(){
self.performSegue(withIdentifier: "goHome", sender: self)
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return noteBookEntries.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell (withIdentifier: "CELL")! as UITableViewCell
cell.textLabel?.text = noteBookEntries[indexPath.row]["title"]
return cell
}

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCellEditingStyle.delete {
noteBookEntries.remove(at: indexPath.row)
UserDefaults.standard.set(noteBookEntries, forKey: "notes")
self.tableView.reloadData()
}
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

self.selectedIndex = indexPath.row

performSegue(withIdentifier: "editNoteBookSegue", sender: nil)
}

override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {
let notesEditorVC = segue.destination as! NewNoteBookEntryViewController

notesEditorVC.navigationItem.title = noteBookEntries[self.selectedIndex] ["title"]
notesEditorVC.noteBodyText = noteBookEntries[self.selectedIndex] ["body"]
notesEditorVC.delegate = self

}


}

error message relating to original segue - this segue works until the second is added

Answer

In your prepareForSegue method first line is:

let notesEditorVC = segue.destination as! NewNoteBookEntryViewController

This method is called for each of your segues. When it is called for your first segue it works totally fine because the destination view controller is, in fact, of type NewNoteBookEntryViewController.

However, when this method is called for your second segue, the destination controller is of different type. So, you get a crash when you force downcast it.

You should add some logic to your prepareForSegue method so that you distinguish between segues. For example:

if segue.identifier == "addNote" {
    let notesEditorVC = segue.destination as! NewNoteBookEntryViewController
    //some other code
}