
关于导航栏,我的处理思路是:完全自定义,每个页面都有完全属于自己的导航栏。
也就是用自定view代替系统的导航栏。
为什么这么做?理由有两点:
- 系统的导航栏是真的难用。原因主要在于系统导航栏这个控件它是属于一组页面的而不是属于一个页面的,这就导致某个页面对它就行调整,所有页面都会受到影响;
- 自定义导航栏很灵活。想放什么控件就放什么控件、想怎么放就怎么放,一切的一切都可以自己把控,更不用担心改了这个页面的导航栏把其他页面的导航栏影响到。
如何封装导航栏?
首先,隐藏系统的导航栏:
self.navigationController.navigationBar.hidden = YES;
当然这个是写到BaseController里的。
注意是:
self.navigationController.navigationBar.hidden = YES;
而不是:
[self.navigationController setNavigationBarHidden:YES];
因为用 setNavigationBarHidden:
会导致返回手势失效,我相信这个是所有人都不愿意看到的。但是有时我们又希望禁掉某个页面的返回手势,那么你可以在这个页面写上这句:
self.navigationItem.hidesBackButton = YES;
把返回按钮给它隐藏掉,返回手势自然就消失了,就是这么6,学会了吗?以后不要再傻傻的写什么代理了。

接着根据你APP的原型,找到使用最频繁的那种导航栏,把它当做基类导航栏,封装。因为一个APP里导航栏肯定不止一种,你要封装的是出现次数最多的那种,比如我这个APP,出现最频繁的就是下面这种导航栏:

一个标题一个返回按钮,背景颜色为主题色。基类导航栏就选它了:
.h文件
@interface CQBaseNaviView : UIView
/** 标题label */
@property (nonatomic, strong) UILabel *titleLabel;
/** 返回按钮 */
@property (nonatomic, strong) UIButton *backButton;
@end
.m文件
@implementation CQBaseNaviView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = THEME_COLOR;
[self setupUI];
}
return self;
}
- (void)setupUI {
// 默认展示标题label与返回按钮
// 标题label
self.titleLabel = [[UILabel alloc] init];
[self addSubview:self.titleLabel];
self.titleLabel.textAlignment = NSTextAlignmentCenter;
self.titleLabel.font = [UIFont systemFontOfSize:20];
self.titleLabel.adjustsFontSizeToFitWidth = YES;
self.titleLabel.textColor = [UIColor colorWithRed:1.00 green:1.00 blue:0.99 alpha:1.00];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.mas_offset(0);
make.height.mas_equalTo(44);
make.left.mas_offset(45);
make.right.mas_offset(-45);
}];
// 返回按钮
self.backButton = [[UIButton alloc] init];
[self addSubview:self.backButton];
[self.backButton setImage:[UIImage imageNamed:@"返回箭头"] forState:UIControlStateNormal];
[self.backButton setImageEdgeInsets:UIEdgeInsetsMake(2, 2, 2, 2)];
[self.backButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(44, 44));
make.bottom.mas_equalTo(self);
make.left.mas_offset(8);
}];
}
@end
接下来是BaseController
BaseController里放什么?
首先是基类导航栏,假定BaseController都有个基类导航栏:
/** 自定义基类导航栏 */
@property (nonatomic, strong) CQBaseNaviView *base_naviView;
然后是通用功能:
- 导航栏上返回按钮点击事件:
/** 返回按钮点击 */
- (void)backButtonClicked {
if (self.presentingViewController) {
[self dismissViewControllerAnimated:NO completion:nil];
} else {
[self.navigationController popViewControllerAnimated:NO];
}
}
- 随时关注Controller的dealloc是否执行:
- (void)dealloc {
NSString *controllerName = NSStringFromClass(self.class);
NSLog(@"页面%@已释放", controllerName);
}
对付内存泄漏最重要的是什么?
是意识!
只有时时刻刻把它放在心上才能从根本上规避内存泄漏。
说得直白点,当你不得不运用leaks工具查找内存泄漏的时候,已经是亡羊补牢了。
在开发之初,就尽量把代码写到最好。不要为了图快就敷衍了事。
在基类里重写dealloc,一旦发现dealloc没有按照预期回调,立即检查这个controller里用到的block。其实说实话,大家都是iOS老油条了,只要稍微长点心,基本上不会出现内存泄漏这种低级错误。
基类导航栏不够用怎么办?
具体情况具体分析。
下面这种导航栏:

只是比基类导航栏在右边多了个按钮,这种情况直接在基类导航栏上add一个button即可。
还有一种更加复杂的导航栏,如下:

这种导航栏跟基类导航栏的差异较大,因此我的思路是隐藏基类导航栏,再定制这个页面的导航栏。

其他注意事项
一定要设置Controller的背景颜色,否则右滑返回的时候Controller会变透明。
网友评论