// 父類 B
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:...
target:self
action:@selector(showPopoverUI:)];
// 子類 A 嘗試覆寫
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:...
target:self.parentViewController // ❌ 錯誤
action:@selector(showPopoverUI:)];
崩潰:+[B showPopoverUI:]: unrecognized selector sent to class。
self.parentViewController 返回**父視圖控制器實例**,但 UIBarButtonItem 的 target 參數期望接收 action 的**對象實例**。showPopoverUI: 是**實例方法**(`-`),子類傳 parentViewController 實例本應可行,但崩潰提示 +[B ...](類方法),說明 parentViewController 在此上下文可能為 nil 或類對象,導致消息發送給類 B 而非實例。viewDidLoad 中調用時,parentViewController 尚未設置(視圖控制器層級關係未建立)。
// 子類 A
- (void)viewDidLoad {
[super viewDidLoad]; // 先調用父類,父類會設置 rightBarButtonItem
// 若需自定義按鈕/行為,直接 target:self
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:...
target:self // ✅ 正確:當前實例
action:@selector(customAction:)];
}
- (void)customAction:(id)sender {
// 子類自定義邏輯
// 若需調用父類邏輯:[super showPopoverUI:sender]; // 父類方法需為 protected/public
}
// 父類 B
- (void)setupRightBarButton {
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:...
target:self
action:@selector(onRightBarButtonTap:)];
}
- (void)onRightBarButtonTap:(id)sender {
[self showPopoverUI:sender]; // 默認實現
}
// 子類 A
- (void)viewDidLoad {
[super viewDidLoad];
// 可選:覆寫按鈕外觀
// self.navigationItem.rightBarButtonItem = ... target:self action:@selector(onRightBarButtonTap:);
}
- (void)onRightBarButtonTap:(id)sender {
// 子類自定義行為
// 或調用父類:[super onRightBarButtonTap:sender];
}
UIBarButtonItem 的 target **必須指向實現 action 方法的實例**(通常是 self)。切勿使用 parentViewController、navigationController 等間接引用,它們可能為 nil、類型不匹配或生命周期不符。父類提供可覆寫鉤子方法,子類通過繼承複用/擴展行為,是最清晰穩健的模式。