Navigation Controller は曲者だ・・・

ふぅ、やっと出来た・・・

Navigation Controller を使った画面を作成していて、はまった点をいくつか・・・

Navigation Controller で検索すると結構な数がヒットする。いろいろ眺めてみたけど、自分の状況とは違っているなと感じる点として、大抵の解説では、Navigation Controller を Storyboard の entry point としている。息の長いアプリで、今年で6年目?となる自分のアプリの場合、既に作成した画面があり、entry point を Navigation Controller にしておらず、既に作成した画面から Navigation Controller を呼び出すことになる。

Navigation Controller を Storyboard に追加すると、TableViewController の他におまけでNavigation Controller がついてくる訳だが、既に作成している画面にボタンを追加し、ボタンを押すと画面を開こうとするとき、指定する画面は、Navigation Controller なのか、あるいは、TableViewController なのかどっちだ?というのがはじめの疑問。

わからないのでどちらも試してみてわかった。TableViewController を指定すると画面上部に navigation bar が出ない。Navigation Controller を指定するとめでたく navigation bar が出る。

ここ結構ややこしい点。navigationItem.title を指定するのは、TableViewController の方でもできる。というか、source 管理の都合、こちらに書く方が良い。しかも、TableViewController では、property で紐付けした記憶がなくても、self.navigationItem.title が通る。ここまで書くと、Navigation Controller の、m, h ファイルをわざわざ作成する必要あるの?と思うけれど、ボタンを押したとき、画面の遷移先と指定指定するのは Navigation Controller なので、m, h ファイルを作っておかないと指定のしようがない。

次にハマったのが、UITableViewController で、行を選択、選択した行に応じて detail 画面の表示内容を変えるという部分。これを実装するには、選択した行の行番号が必要になるわけだ。 画面遷移は segue にしている。

で、行を選んだら segue 呼ぶってのはどうするんだ?正解は、次のように、performSegueWithIdentifier を使う。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

    

    [self performSegueWithIdentifier:@"segueName" sender:self];

 

    [tableView deselectRowAtIndexPath:indexPath animated:YES]; // 選択状態の解除

 

 

}

performSegueWithIdentifier が呼ばれると、以下の method が呼ばれる。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

この method で、選択した行番号に応じて、detail 画面で表示する内容を変えてやればよい・・・のだけれど、tableView.indexPathForSelectedRow.row に、選択した行の値が入らない。常に 0 が返る。

うーんハマった。しょうがないので、global 変数を用意し、上記の didSelectRowAtIndexPath 内で、global 変数に選択した行を保存するとうまく行く・・・けど、これ、絶対おかしいなぁ・・・・

原因は、「選択状態の解除」を performSegueWithIdentifier の前に書いていたからで、performSegueWithIdentifier が呼ばれるときには選択が解除されていたという・・・・

上記の記述は正しい位置に選択状態の解除を書いた例。ふぅ、やっとこれでうまく書けたよ。