You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS导航栏按钮点击报错:Unrecognized selector sent to UITabBarController实例问题排查

问题分析与解决方案

这个问题我之前也碰到过,核心原因是你搞混了 selector 的 target 对象!

你的错误日志已经给出了关键线索:-[UITabBarController returnToGalleryScreenTab]: unrecognized selector sent to instance —— 系统尝试给 UITabBarController 发送 returnToGalleryScreenTab 这个消息,但它根本没有这个方法。

看你扩展里的这段代码:

button.addTarget(self, action: selector, for: .touchUpInside)

这里的 self 是调用该方法的 TabBarController 实例,而你的 returnToGalleryScreenTab 和 routeToAddPhotoForm 方法是定义在当前的 ViewController 里的。当按钮点击时,系统会按照你设置的 target(TabBarController)去查找对应的 selector,找不到自然就报错了。

两种可行的修复方案

方案1:给扩展方法添加 target 参数

修改 TabBarController 的扩展,让它同时接收 selector 和对应的 target 对象(也就是你的 ViewController),这样按钮的 target 就会指向正确的对象:

extension UITabBarController {
    func setLeftNavBarView(target: Any?, selector: Selector) {
        let button = UIButton(type: .custom)
        button.setTitle("Cancel", for: .normal)
        button.setTitleColor(UIColor(rgb: 0xFF5F5F5F), for: .normal)
        button.titleLabel?.font = UIFont(name: "Roboto", size: 15)
        // 这里把 target 换成传入的对象,而非 TabBarController 自身
        button.addTarget(target, action: selector, for: .touchUpInside)
        button.titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        let barButton = UIBarButtonItem(customView: button)
        navigationItem.leftBarButtonItem = barButton
    }
    
    func setRightNavBarView(target: Any?, selector: Selector) {
        let button = UIButton(type: .custom)
        button.setTitle("Next", for: .normal)
        button.setTitleColor(UIColor(rgb: 0xFFCF497E), for: .normal)
        button.titleLabel?.font = UIFont(name: "Roboto-Bold", size: 15)
        // 同样替换 target
        button.addTarget(target, action: selector, for: .touchUpInside)
        button.titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        let barButton = UIBarButtonItem(customView: button)
        navigationItem.rightBarButtonItem = barButton
    }
}

然后在你的 ViewController 里调用时,把当前 VC 作为 target 传进去:

override func viewDidLoad() {
    super.viewDidLoad()
    // ... 其他代码
    self.tabBarController?.setLeftNavBarView(target: self, selector: #selector(self.returnToGalleryScreenTab))
    self.tabBarController?.setRightNavBarView(target: self, selector: #selector(self.routeToAddPhotoForm))
}

方案2:直接在 ViewController 里设置导航栏按钮(更推荐)

其实导航栏的 navigationItem 是属于当前 ViewController 的属性,没必要绕到 TabBarController 里设置。你可以把按钮创建逻辑直接放到当前 VC 中,这样逻辑更直观,也彻底避免了 target 混淆的问题:

override func viewDidLoad() {
    super.viewDidLoad()
    // ... 其他代码
    setupNavigationBarButtons()
}

private func setupNavigationBarButtons() {
    // 配置左侧 Cancel 按钮
    let leftButton = UIButton(type: .custom)
    leftButton.setTitle("Cancel", for: .normal)
    leftButton.setTitleColor(UIColor(rgb: 0xFF5F5F5F), for: .normal)
    leftButton.titleLabel?.font = UIFont(name: "Roboto", size: 15)
    leftButton.addTarget(self, action: #selector(returnToGalleryScreenTab), for: .touchUpInside)
    navigationItem.leftBarButtonItem = UIBarButtonItem(customView: leftButton)
    
    // 配置右侧 Next 按钮
    let rightButton = UIButton(type: .custom)
    rightButton.setTitle("Next", for: .normal)
    rightButton.setTitleColor(UIColor(rgb: 0xFFCF497E), for: .normal)
    rightButton.titleLabel?.font = UIFont(name: "Roboto-Bold", size: 15)
    rightButton.addTarget(self, action: #selector(routeToAddPhotoForm), for: .touchUpInside)
    navigationItem.rightBarButtonItem = UIBarButtonItem(customView: rightButton)
}

@objc func routeToAddPhotoForm() {
    self.presenter?.routeToAddPhotoForm()
}
@objc func returnToGalleryScreenTab() {
    self.tabBarController?.selectedIndex = 0
}

这种方式所有逻辑都集中在当前 VC,target 明确指向自身,不会再出现 selector 找不到的问题。

内容的提问来源于stack exchange,提问作者Ivanius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 20:44:09