iOS 11自定义LeftBarButtonItem首次显示后二次隐藏问题求助
看起来你遇到的是iOS 11导航栏布局逻辑变化导致的兼容性问题,iOS 10及之前的系统对自定义导航栏按钮的frame处理更宽松,但iOS 11改用Auto Layout管理导航栏元素,这就暴露了代码里的几个潜在问题,下面给你分步解决:
问题根源分析
从你提供的代码片段来看,有两个核心问题:
- 你创建了
UIBarButtonItem但没有把它赋值给_backTabBarItem,导致每次调用setBackButton时,都会重新创建新的按钮实例,在iOS 11的布局逻辑下,重复替换按钮会触发视图层级的异常。 - 直接给
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
相关产品推荐
相关产品推荐

