Storyboard で UITableView の didSelectRowAtIndex が呼ばれた時、どうやって prepareForSegue から destinationViewController にパラメータを伝えるのか?


問題点の整理

Storyboard で UITableView を使う時、Interface Builder から Prototype Cell を配置し、その種のセルから Segue で次の ViewController につないであげると、実行時にそのセルをタップすると、次のViewController に遷移します。

せっかく TableView からセルを選んだのですから、多くの場合は 次の ViewController で選んだセルに相当する情報を、次の ViewController に伝えたい筈です。問題はそれをどのように実現するかです。

セルをタップすると、UITableView の delegate の tableView:didSelectRowAtIndexPath: が呼ばれます。が、この時点では 次の ViewController の尻尾は掴めないので、パラメータを伝える事は出来ません。

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    // where is the next view controller!? how can I get it?
}

prepareForSegue:sender: が呼ばれた時は、「それってどのセル」でしたっけ?となります。

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // which cell was that!?
}

Stack Overflow

Use didSelectRowAtIndexPath or prepareForSegue method for UITableView?
http://stackoverflow.com/questions/8130600/use-didselectrowatindexpath-or-prepareforsegue-method-for-uitableview

Stack Overflow にもいくつか方法が挙げられています。セルの tag に rowIndex を仕込んだり苦労されているみたいです。

UITableView の indexPathForCell を使えば…

しかし、prepareForSegue の sender はタップした cell が送られてくるのであれば、self.tableView.indexPathForCell(sender as! UITableViewCell) を使って indexPath がわかります。そこで indexPath に相当するパラメータを次の ViewController へパラメータとして渡してあげれば目的達成です。

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let cell = sender as? UITableViewCell {
        let indexPath = self.tableView.indexPathForCell(cell)!
        assert(segue.destinationViewController.isKindOfClass(DetailViewController))
        let detailViewController = segue.destinationViewController as! DetailViewController
        detailViewController.item = self.items[indexPath.row]
    }
}