在「排行榜選單」(MenuVC) 推入「遊戲」(GameVC) 時,GameVC 需透過 Delegate 將最高分回傳 MenuVC 更新。常見錯誤:在 viewDidLoad 中 [[ViewController alloc] init] 建立新實例設定 delegate,而非設定給正在顯示的實例。
// MenuVC.m
- (void)viewDidLoad {
[super viewDidLoad];
GameVC *vc = [[GameVC alloc] init]; // 錯誤:建立新實例,非即將呈現的那個
vc.delegateHighScore = self;
}
// 呈現時 (如按鈕點擊)
- (IBAction)startGame:(id)sender {
GameVC *vc = [[GameVC alloc] init]; // 另一個新實例
[self presentViewController:vc animated:YES completion:nil];
// 真正呈現的 vc 沒有設定 delegate!
}
// MenuVC.m
- (IBAction)startGame:(id)sender {
GameVC *gameVC = [[GameVC alloc] init]; // 或從 Storyboard 實例化
gameVC.delegateHighScore = self; // 關鍵:設定給即將呈現的實例
[self presentViewController:gameVC animated:YES completion:nil];
}
// 若使用 Storyboard + Segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"ShowGame"]) {
GameVC *gameVC = (GameVC *)segue.destinationViewController;
gameVC.delegateHighScore = self; // 在 prepareForSegue 設定
}
}
// GameVC.h
@protocol HighScoreDelegate
- (void)updateHighScore:(NSInteger)score;
@end
@interface GameVC : UIViewController
@property (nonatomic, weak) id delegateHighScore;
@property (nonatomic, assign) NSInteger score;
@end
// GameVC.m
- (void)gameOver {
[self.delegateHighScore updateHighScore:self.score]; // 回呼
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Game Over"
message:[NSString stringWithFormat:@"Score: %ld", (long)self.score]
delegate:self
cancelButtonTitle:@"Main Menu"
otherButtonTitles:@"Restart", nil];
[alert show];
}
// AlertView 點擊處理 (若需回主選單)
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
[self dismissViewControllerAnimated:YES completion:nil]; // 回主選單
} else {
[self restartGame];
}
}
alloc/init 的新實例。prepareForSegue: 設定。presentViewController: 前設定。weak 避免循環保留。若僅需從子頁面返回資料給父頁面,可使用 Unwind Segue 簡化流程,無需手寫 Delegate 協定。