首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

iOS 子類調用父類導航欄按鈕設置方法導致崩潰:target 必須指向 self 而非 parentViewController

     編輯:程式設計綜合問答

崩潰代碼


// 父類 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 的**對象實例**。
  • 父類 B 中 showPopoverUI: 是**實例方法**(`-`),子類傳 parentViewController 實例本應可行,但崩潰提示 +[B ...](類方法),說明 parentViewController 在此上下文可能為 nil 或類對象,導致消息發送給類 B 而非實例。
  • 更可能:子類 A 的 viewDidLoad 中調用時,parentViewController 尚未設置(視圖控制器層級關係未建立)。

修正:target 恒為 self


// 子類 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、類型不匹配或生命周期不符。父類提供可覆寫鉤子方法,子類通過繼承複用/擴展行為,是最清晰穩健的模式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved