在 iOS 開發中,UITableView 是最常用的列表展示控件。當使用 Storyboard 搭建介面時,如何在用戶點選某一列後,順利導航到下一個視圖(通常稱為 Detail View)並傳遞相應數據,是初學者常見的疑問。
許多初學者會在 didSelectRowAtIndexPath 方法中直接實例化目標 ViewController,然後呼叫 [self.view addSubview:dv.view]。這樣做雖然能顯示視圖,但破壞了導航控制器的堆疊管理,導致返回鍵、導航欄等功能失效,且視圖控制器的生命週期方法(如 viewWillAppear)不會被正確調用。
// ❌ 錯誤做法
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.dv = [[Detail alloc] initWithNibName:@"Detail" bundle:nil];
dv.dic = [self.arr1 objectAtIndex:indexPath.row];
[self.view addSubview:dv.view];
}
標準流程是將列表視圖控制器嵌入 UINavigationController,然後在點擊事件中呼叫 pushViewController:animated:。這樣能保持導航棧完整,自動處理返回邏輯與動畫過渡。
// ✅ 正確做法
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 1. 從 Storyboard 實例化目標 VC(假設 Storyboard ID 為 "DetailVC")
DetailViewController *detailVC = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailVC"];
// 2. 傳遞數據
detailVC.dataDictionary = self.dataArray[indexPath.row];
// 3. Push 到導航堆疊
[self.navigationController pushViewController:detailVC animated:YES];
// 4. 取消選中狀態(可選)
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Storyboard ID(如 "DetailVC")。NSDictionary,利於型別檢查與維護。若不想手寫跳轉代碼,可在 Storyboard 中從 Cell 直接拖曳 Segue 到目標 VC,選擇 Show (Push),然後覆寫 prepareForSegue:sender: 傳值:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"ShowDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
DetailViewController *dest = segue.destinationViewController;
dest.dataDictionary = self.dataArray[indexPath.row];
}
}
這種方式更符合 Storyboard 設計哲學,代碼更乾淨,也方便視覺化管理轉場邏輯。