Search code examples
iosswiftuitableviewseguenavigationitem

Can't set UINavigationItem title programatically on initial load


I'm am performing a segue (via storyboard) from a TableViewController (embedded in a NavigationController) to another TableViewController. I.e Selecting a cell and presenting another TableView on which i would like to display the selected cell's text as the next views title.

I am achieving this however not 100% correctly. On the first initial selection of a cell the navigationItem title is not set. Only once i navigate back and then again forward through that same cell, is the title set.

The first snippet is my first viewController that I'm selecting a cell on where I am setting the destinationViewControllers variable with the selected cells title.

    var valueToPass:String?
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        print("You selected cell #\(indexPath.row)!")

        // Get Cell Label
        let indexPath = tableView.indexPathForSelectedRow!;
        let currentCell = tableView.cellForRowAtIndexPath(indexPath) as UITableViewCell!;

        valueToPass = currentCell.textLabel!.text
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    if (segue.identifier == "tripSegue") {

        // initialize new view controller and cast it as your view controller
        let viewController = segue.destinationViewController as! TripTableViewController
        // setting the view controllers property that will store the passed value
        viewController.passedValue = valueToPass
    }

}

The second snippet is from the destinationViewController setting the navigationItem title.

var passedValue: String?

override func viewDidLoad() {
    super.viewDidLoad()

    self.navigationItem.title = passedValue
}

Solution

  • This is because prepareForSegue is called before didSelectRowAtIndexPath. So the first time you select a row, valueToPass is nil. prepareForSegue is called while valueToPass is still nil and you pass it, then after you pass that, didSelectRowAtIndexPath is called setting valueToPass to the desired value, which is what's passed the next time you select a row.

    You need to do it all in prepareForSegue.

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    
    if (segue.identifier == "tripSegue") {
           // Get Cell Label
           let indexPath = self.tableView.indexPathForSelectedRow!;
           let currentCell = self.tableView.cellForRowAtIndexPath(indexPath) as UITableViewCell!;
           // initialize new view controller and cast it as your view controller
           let viewController = segue.destinationViewController as! TripTableViewController
           // setting the view controllers property that will store the passed value
           viewController.passedValue = currentCell.textLabel!.text
    
        }
    }