Irohabook
0
2498

SwiftでtableViewからデータを受け渡す(didSelectRowAtとprepareを両方使うとエラーになる)

Swiftで「TableViewのcellをタッチして詳細画面に移る」という画面遷移を考える。遷移前はTableView(またはTableViewを包むViewController)であり、遷移後は通常のViewControllerである。

前提

遷移前 ViewControllerのTableView
遷移後 ViewController

ストーリーボードでセグエを作っているとする。セグエは必ずTableViewのcellから引っ張る。identifierもきちんと設定しておく。セグエの始点と終点、identifierを正しく設定しないとエラーが出る。

結論:didSelectRowAtではなくprepareを使う

SwiftでtableViewからデータを受け渡すとき、didSelectRowAtはなるべく使わない。

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

代わりにprepareを使う。

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if ( segue.identifier == "yourViewIdentifier" ) {
        let x = self.YourTableView.indexPathForSelectedRow
        let y = x?.row
        let post = self.posts[y!]
        let p : PostViewController = segue.destination as! PostViewController
        p.param = post.thumbnail
    }
}

イベントが2回発生するエラー

didSelectRowAtとprepareを両方とも用意していると、画面遷移のときにイベントが2回発生する。それ自体はエラーでない。画面遷移でデータを渡すときにエラーになる。

didSelectRowAtがあってもなくてもprepareは必要になる(ようだ)。prepareは必要だが、didSelectRowAtはあってもなくてもかまわない。そしてデータをきちんと渡すためには、prepareだけで十分である。

prepare内でindexPathForSelectedRowを使い、cellの順番を取得する

画面がリストから詳細に移るときを考える。このとき、イベントのあったcellが何番目のcellか、cellにどのような情報が含まれているかがわからないといけない。

多くのサンプルではdidSelectRowAtを使うが、結局はprepareを使ったほうが早い。そしてエラーがない。prepareでcellの情報を知るには、indexPathForSelectedRowというメソッドを使う。

indexPathForSelectedRowは、遷移前のviewのIBOutletで定義しているフィールドのメソッドである。

@IBOutlet weak var YourTableView: UITableView!
次の記事

UICollectionView