The prepare(for segue: )
function runs, but the data is not sent to my destination ViewController. I am getting following error when loading that VC's collection view which has to receive the data:
Unexpectedly found nil while unwrapping an Optional value
I have confirmed that the segue type is a selection
segue, the segue identifier is correct, and that the views work as far as displaying dummy data.
First view controller (DrawerVC):
let realm = try! Realm()
var allDrawers: Results<Drawer>?
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("goToTool segue")
performSegue(withIdentifier: "goToTool", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToTool" {
print("Prepare for segue from drawerVC ran") // this runs!
let destinationVC = segue.destination as! ToolVC
if let indexPath = tableView.indexPathForSelectedRow {
destinationVC.selectedDrawer = allDrawers?[indexPath.row]
print("Selected drawer set to index path") // doesn't run :(
}
} else if segue.identifier == "goToEditCategory" {
_ = segue.destination as! EditCategoryVC
}
}
Destination view controller (ToolVC):
let realm = try! Realm()
var allTools: Results<Tool>?
var selectedDrawer: Drawer? {
didSet{
// doesn't run since selectedDrawer was never set :(
print("The selected drawer changed from \(oldValue) to \(selectedDrawer?.title)")
loadTools()
}
}
func loadTools() {
allTools = selectedDrawer?.tools.sorted(byKeyPath: "title", ascending: false)
toolCollectionView.reloadData() // this is where I get the optional value error
}
You are making a very common mistake.
In the destination view controller you are accessing the table view in loadTools()
which is not connected yet at the moment you assign the selected drawer. Therefore the table view is nil
and causes the crash.
A solution is to remove the didSet
observer
var selectedDrawer: Drawer?
and load the data in viewDidLoad
func viewDidLoad() {
super.viewDidLoad()
if let drawer = selectedDrawer {
allTools = drawer.tools.sorted(byKeyPath: "title", ascending: false)
toolCollectionView.reloadData()
}
}
And if the segue is connected from the cell to the destination view controller remove the didSelectRowAt
method.