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

iOS 11自定义LeftBarButtonItem首次显示后二次隐藏问题求助

解决iOS 11下自定义LeftBarButtonItem二次点击后隐藏的问题

看起来你遇到的是iOS 11导航栏布局逻辑变化导致的兼容性问题,iOS 10及之前的系统对自定义导航栏按钮的frame处理更宽松,但iOS 11改用Auto Layout管理导航栏元素,这就暴露了代码里的几个潜在问题,下面给你分步解决:

问题根源分析

从你提供的代码片段来看,有两个核心问题:

  1. 你创建了UIBarButtonItem但没有把它赋值给_backTabBarItem,导致每次调用setBackButton时,都会重新创建新的按钮实例,在iOS 11的布局逻辑下,重复替换按钮会触发视图层级的异常。
  2. 直接给UIButton设置frame在iOS 11的Auto Layout环境下不生效,按钮的尺寸会被系统重置,导致看起来像是"隐藏"了。

修复方案

1. 正确持有自定义BarButtonItem实例

首先要确保你只创建一次UIBarButtonItem,并把它赋值给你的成员变量,避免重复创建:

- (void)setBackButton {
    if (_backTabBarItem == nil) {
        UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
        [backButton setImage:[UIImage imageNamed:@"icon_back"] forState:UIControlStateNormal];
        [backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
        [backButton addTarget:self action:@selector(popViewController) forControlEvents:UIControlEventTouchUpInside];
        
        // 关键:把创建的BarButtonItem赋值给成员变量,确保只创建一次
        _backTabBarItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
    }
    // 直接复用已创建的实例
    self.navigationItem.leftBarButtonItem = _backTabBarItem;
}

注意:请确保_backTabBarItem是强引用的属性(在头文件中声明为@property (strong, nonatomic) UIBarButtonItem *backTabBarItem;),避免被提前释放。

2. 适配iOS 11的Auto Layout布局

iOS 11中导航栏使用Auto Layout管理子视图,直接设置frame会被系统覆盖,所以需要给自定义按钮添加明确的尺寸约束:

- (void)setBackButton {
    if (_backTabBarItem == nil) {
        // 初始化按钮时不要设置frame,改用Auto Layout约束
        UIButton *backButton = [[UIButton alloc] init];
        [backButton setImage:[UIImage imageNamed:@"icon_back"] forState:UIControlStateNormal];
        [backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
        [backButton addTarget:self action:@selector(popViewController) forControlEvents:UIControlEventTouchUpInside];
        
        // 添加尺寸约束,确保按钮在iOS 11下能正确显示
        [backButton.widthAnchor constraintEqualToConstant:30].active = YES;
        [backButton.heightAnchor constraintEqualToConstant:30].active = YES;
        
        _backTabBarItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
    }
    self.navigationItem.leftBarButtonItem = _backTabBarItem;
}

3. 优化视图控制器生命周期中的调用时机

建议在viewWillAppear:中调用setBackButton,而不是重复在多个生命周期方法中调用,避免不必要的视图层级变更:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self setBackButton];
}

额外验证点

  • 检查你的popViewController方法是否正确实现,确保没有在pop时意外修改了导航栏的按钮状态;
  • 如果你的导航控制器有自定义的导航栏子类,也要检查是否在iOS 11下有布局逻辑的冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:13:12