呼叫 performSegueWithIdentifier:@\"login\" 時拋出 NSInvalidArgumentException: Receiver has no segue with identifier 'login',但 Storyboard 中已設定相同 Identifier。
| 原因 | 檢查方式 | 解決 |
|---|---|---|
| Identifier 拼寫不一致 | Storyboard 選中 Segue → Attributes Inspector → Identifier | 完全複製貼上,區分大小寫 |
| Segue 連接錯誤 | 確認 Segue 從**正確的 ViewController** 拖曳而出 | 重新拖曳:Ctrl+Drag 從來源 VC 到目標 VC |
| 來源 VC 非 Storyboard 實例化 | 代碼中用 new MyVC() 或 [[MyVC alloc] init] | 必須用 instantiateViewControllerWithIdentifier: |
| 在 viewDidLoad 呼叫但 Segue 尚未準備好 | viewDidLoad 時 View 階層未完成 | 移至 viewDidAppear: 或按鈕動作中 |
| Navigation Controller 結構問題 | Segue 類型為 Show/Show Detail 但無 Navigation Controller | 確認 Segue 類型與容器匹配 |
// 失敗:在回調中呼叫
- (void)sinaweiboDidLogIn:(SinaWeibo *)sinaweibo {
[self performSegueWithIdentifier:@"login" sender:self]; // 崩潰
}
// 成功:在 viewDidLoad 中呼叫
- (void)viewDidLoad {
if (token != nil) {
[self performSegueWithIdentifier:@"login" sender:self]; // 正常
}
}
推測原因:回調 sinaweiboDidLogIn: 可能在**非主執行緒**或 **ViewController 尚未加入視圖階層**時觸發,導致 Segue 機制失效。
- (void)sinaweiboDidLogIn:(SinaWeibo *)sinaweibo {
[self saveWeiboInfo];
NSLog(@"uid= %@ accessToken= %@", sinaweibo.userID, sinaweibo.accessToken);
// 確保在主執行緒執行 UI 操作
dispatch_async(dispatch_get_main_queue(), ^{
// 額外檢查:確認 Segue 存在
if ([self respondsToSelector:@selector(performSegueWithIdentifier:sender:)]) {
[self performSegueWithIdentifier:@"login" sender:self];
} else {
NSLog(@"ERROR: performSegueWithIdentifier 不可用,可能 VC 未正確載入");
// 替代方案:手動跳轉
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *target = [sb instantiateViewControllerWithIdentifier:@"TargetVCID"];
[self.navigationController pushViewController:target animated:YES];
}
});
}
// 列出所有可用 Segue (在 viewDidAppear 中執行)
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// 這需要私有 API,僅除錯用
// NSLog(@"Available segues: %@", [self valueForKey:@"storyboardSegueTemplates"]);
}
// 取代 Segue,直接在代碼中跳轉
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
TargetViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"TargetVCID"];
vc.receivedToken = sinaweibo.accessToken; // 直接傳遞資料
[self.navigationController pushViewController:vc animated:YES];
// 或 Present
[self presentViewController:vc animated:YES completion:nil];
優勢:無 Identifier 字串錯誤風險、資料傳遞型別安全、易於單元測試。