Q:

Issue when performing a segue on a tableview cell

I'm currently learning Swift and trying to perform a segue when the user taps on one of the tableview cells that the app presents. At the moment, whenever the user performs this action, the next view controller is loaded successfully, but it seems that, for some reason, I cannot access any of its UI elements, as each time that I try to do it, I end up getting this error:
fatal error: unexpectedly found nil while unwrapping an Optional value 
The error points to the line in which I try to modify the text of one of the labels that are displayed on the next view controller
This is the didSelectRowAt function:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
    self.performSegue(withIdentifier: "segue1", sender: self)
}

and this is the prepareForSegue function:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "segue1" {
        let destinationVC = segue.destination as! UserViewController
        let selectedRow = tableView.indexPathForSelectedRow!
        let selectedCell = tableView.cellForRow(at: selectedRow) as! CustomCell

        destinationVC.usernameLabel.text = selectedCell.userName.text //this is where the error is pointing to
        destinationVC.bioLabel.text = selectedCell.bio.text
        destinationVC.userImage.image = selectedCell.photo.image

    }
}

I have no idea about what is causing this problem. My goal is to pass the data from the tapped cell to the next view controller, but this obviously is preventing me from doing so. Does anyone know how I can fix this? Thanks in advance.

A:

Note: I assumed that userName and bio were both UITextFields
Why don't you try something like this?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "segue1" {
        let destination = segue.destination as! UserViewController
        // Use of optional binding to make sure an indexPath exists
        if let indexPath = tableView.indexPathForSelectedRow {
            let cell = tableView.cellForRow(at: IndexPath(row: indexPath.row, section: indexPath.section)) as! CustomCell
            // Notice how we are not directly updating the label as before.
            destination.usernameText = cell.userName?.text
            destination.bioText = cell.bio?.text
        }
    }

}

Now in UserViewController:
@IBOutlet weak var usernameLabel: UILabel!
@IBOutlet weak var bioLabel: UILabel!
// What we will be passing the text to instead.
var usernameText: String?
var bioText: String?

override func viewDidLoad() {
    super.viewDidLoad()
    // update the labels with the text from the proper cell.
    usernameLabel?.text = usernameText
    bioLabel?.text = bioText
}

You can just do the same for your image, just different types. This has to do with the outlets not being allocated when used in prepare(for segue:).

