还在为每个视图控制器都要自定义导航栏按钮而烦躁吗?还在为每个视图控制器的列表都要添加一遍上拉刷新下拉加载而焦心吗?还在为每个列表添加空白提示而烦恼吗?不要怕,你需要一个基类,一个救你于水火的VC的基类!
当你看到一个VC中几千行代码的时候你是绝望的,崩溃的!那些每个界面都要写的代码就是冗余代码,我们完全可以在vc的基类中来写这些代码,只要vc继承基类vc,那么我们只需要一句代码就可以完成创建导航左右按钮,为列表添加上拉上推事件等等繁琐而相同的事情!既能优化界面,又能让你的代码略微提升那么一点逼格,何乐而不为呢,是吧老铁~ 好了,废话结束,进入正题!
首先在返回按钮跟设置的普通返回按钮不同的时候,或者导航栏右按钮需要有点击事件的时候,一般我们会选择自定义导航栏左右按钮。当一个APP有多个界面需要自定义左右按钮的时候,这些代码充斥在多个视图控制器中会显得杂乱和冗余,这时候我们就可以在基类VC中这么写,.h文件
typedef void(^navigationBtnBlock)(UIButton *navBtn);
@interface BaseViewController : UIViewController
/** navigationBar item click */
@property (nonatomic, copy)navigationBtnBlock navBtnAction;
@end
.m文件
#pragma mark ------- set nav left item
-(void)createBackBtnWithImageName:(NSString *)imageName{
UIButton *btn_back = [UIButton buttonWithType:UIButtonTypeCustom];
btn_back.frame = CGRectMake(0, 0, 40, 30);
btn_back.contentEdgeInsets = UIEdgeInsetsMake(0, -2, 0, 0);
btn_back.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
[btn_back setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
btn_back.tag = 9;
//保证所有touch事件button的highlighted属性为NO,即可去除高亮效果
[btn_back addTarget:self action:@selector(preventFlicker:) forControlEvents:UIControlEventAllTouchEvents];
[btn_back addTarget:self action:@selector(popToLastVC:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *leftItem = [[UIBarButtonItem alloc]initWithCustomView:btn_back];
self.navigationItem.leftBarButtonItem = leftItem;
}
-(void)popToLastVC:(UIButton *)sender{
NSArray *viewControllers = self.navigationController.viewControllers;
if (viewControllers.count == 0) {
return;
}
if (self.navBtnAction) {//如果vc中调用了block回调就走自己的回调
self.navBtnAction(sender);
}else{//如果vc中没有调用block回调,直接返回到到上级页面
[self.navigationController popViewControllerAnimated:YES];
}
}
#pragma mark ------- wipe out button highlight
-(void)preventFlicker:(UIButton *)sender{
sender.highlighted = NO;
}
#pragma mark ------- set nav right item
-(void)createNavRightBtnWithImageName:(NSString *)imageName{
UIButton *btn_right = [UIButton buttonWithType:UIButtonTypeCustom];
btn_right.frame = CGRectMake(0, 0, 40, 30);
btn_right.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 2);
btn_right.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
[btn_right setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
btn_right.tag = 10;
//保证所有touch事件button的highlighted属性为NO,即可去除高亮效果
[btn_right addTarget:self action:@selector(preventFlicker:) forControlEvents:UIControlEventAllTouchEvents];
[btn_right addTarget:self action:@selector(rightBtnClick:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *rightItem = [[UIBarButtonItem alloc]initWithCustomView:btn_right];
self.navigationItem.rightBarButtonItem = rightItem;
}
-(void)rightBtnClick:(UIButton *)sender{
NSArray *viewControllers = self.navigationController.viewControllers;
if (viewControllers.count == 0) {
return;
}
if (self.navBtnAction) {//如果vc中调用了block回调就走自己的回调
self.navBtnAction(sender);
}else{//如果vc中没有调用block回调,直接返回到到上级页面
[self.navigationController popViewControllerAnimated:YES];
}
}
在继承基类的VC中我们可以这样调用
[self createBackBtnWithImageName:@"图片名字"];
//如果不设置这个block回到,点击返回按钮就会直接返回上一级界面
self.navBtnAction = ^(UIButton * _Nonnull navBtn) {
//这里可以通过按钮的tag值来判断点击的是按钮
};
列表是大部分APP都会频繁使用的控件,但是为tableView设置上推和下拉的事件却是比较繁琐的,我们可以在基类中这样来写,.h文件代码如下:
typedef void(^tableViewRefreshBlock)(NSInteger pageNum);
typedef void(^navigationBtnBlock)(UIButton *navBtn);
@interface BaseViewController : UIViewController
/** tableView pull or push action */
@property (nonatomic, copy)tableViewRefreshBlock tableViewRefresh;
/** add tableview pull and push action */
-(void)addTableHeaderRefresh:(BOOL)headerRefresh tableFooterRefresh:(BOOL)footerRefresh;
@end
.m文件代码
#pragma mark ------- tableView pull and push action
-(void)addTableHeaderRefresh:(BOOL)headerRefresh tableFooterRefresh:(BOOL)footerRefresh{
if (headerRefresh) {
MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(reloadData)];
header.lastUpdatedTimeLabel.hidden = YES;
[header setTitle:@"拼命加载中..." forState:MJRefreshStateRefreshing];
[header setTitle:@"下拉刷新数据~" forState:MJRefreshStateIdle];
self.tableView.mj_header = header;
}
if (footerRefresh) {
MJRefreshAutoNormalFooter *footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)];
[footer setTitle:@"我是有底线的~" forState:MJRefreshStateNoMoreData];
[footer setTitle:@"拼命加载中..." forState:MJRefreshStateRefreshing];
[footer setTitle:@"上拉更多精彩~" forState:MJRefreshStateIdle];
footer.stateLabel.textColor = [UIColor lightGrayColor];
self.tableView.mj_footer = footer;
}
}
-(void)reloadData{
_pageNum = 1;
if (self.tableViewRefresh) {
self.tableViewRefresh(_pageNum);
}
}
-(void)loadMoreData{
_pageNum ++;
if (self.tableViewRefresh) {
self.tableViewRefresh(_pageNum);
}
}
-(void)tableViewEndRefresh{
[self.tableView.mj_header endRefreshing];
[self.tableView.mj_footer endRefreshing];
}
在继承基类的VC中我们可以这样调用
//设置为YES就添加事件,为NO则不添加事件
[self addTableHeaderRefresh:YES tableFooterRefresh:YES];
self.tableViewRefresh = ^(NSInteger pageNum) {
//回调回来当前的pageNum
//这里可以进行数据请求
};
还有一些其他的方法,提示框,空白页等等诸如此类都已在基类中设置,我总结了一下分享给大家,一起学习~
typedef void(^navigationBtnBlock)(UIButton *navBtn);
typedef void(^tableViewRefreshBlock)(NSInteger pageNum);
@interface BaseViewController : UIViewController
/** navigationBar item click */
@property (nonatomic, copy)navigationBtnBlock navBtnAction;
/** tableView pull or push action */
@property (nonatomic, copy)tableViewRefreshBlock tableViewRefresh;
/** tableView */
@property (nonatomic, strong)UITableView *tableView;
/** tableView current page */
@property (nonatomic, assign)NSInteger pageNum;
/** set custom navigation leftItem */
-(void)createBackBtnWithImageName:(NSString *)imageName;
/** set navigationbar backgroundColor */
-(void)setNavigationBarBackgroundImageWithColor:(UIColor *)color;
/** set custom navigation rightItem */
-(void)createNavRightBtnWithImageName:(NSString *)imageName;
/** show custom aleartView */
-(void)showMessageBottomWithText:(NSString *)text;
/** add tableview pull and push action */
-(void)addTableHeaderRefresh:(BOOL)headerRefresh tableFooterRefresh:(BOOL)footerRefresh;
/** show custom hud */
-(void)showCustomMessageViewWithText:(NSString *)text;
/** hide custom hud */
-(void)hiddenCustomMessageView;
/** show custom activeIndicator*/
-(void)showCustomActiveIndicator;
/**hide custom activeIndicator*/
-(void)hiddenCustomActiveIndicator;
@end
.m文件
@interface BaseViewController (){
UIImageView *navBarHairlineImageView;
UIActivityIndicatorView *_activityIndicator;
}
@end
@implementation BaseViewController
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
navBarHairlineImageView.hidden = YES;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
//prevent view move down
self.automaticallyAdjustsScrollViewInsets = NO;
//set view backgroundColor
self.view.backgroundColor = [UIColor whiteColor];
//set nav backgroundColor
[self setNavigationBarBackgroundImageWithColor:[UIColor whiteColor]];
//wipe out the black line under the navigation bar
UINavigationBar *navigationBar = self.navigationController.navigationBar;
navBarHairlineImageView = [self slnFindHairlineImageViewUnder:navigationBar];
}
#pragma mark ------- set nav left item
-(void)createBackBtnWithImageName:(NSString *)imageName{
UIButton *btn_back = [UIButton buttonWithType:UIButtonTypeCustom];
btn_back.frame = CGRectMake(0, 0, 40, 30);
btn_back.contentEdgeInsets = UIEdgeInsetsMake(0, -2, 0, 0);
btn_back.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
[btn_back setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
btn_back.tag = 9;
//保证所有touch事件button的highlighted属性为NO,即可去除高亮效果
[btn_back addTarget:self action:@selector(preventFlicker:) forControlEvents:UIControlEventAllTouchEvents];
[btn_back addTarget:self action:@selector(popToLastVC:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *leftItem = [[UIBarButtonItem alloc]initWithCustomView:btn_back];
self.navigationItem.leftBarButtonItem = leftItem;
}
-(void)popToLastVC:(UIButton *)sender{
NSArray *viewControllers = self.navigationController.viewControllers;
if (viewControllers.count == 0) {
return;
}
if (self.navBtnAction) {//如果vc中调用了block回调就走自己的回调
self.navBtnAction(sender);
}else{//如果vc中没有调用block回调,直接返回到到上级页面
[self.navigationController popViewControllerAnimated:YES];
}
}
#pragma mark ------- wipe out button highlight
-(void)preventFlicker:(UIButton *)sender{
sender.highlighted = NO;
}
#pragma mark ------- set nav right item
-(void)createNavRightBtnWithImageName:(NSString *)imageName{
UIButton *btn_right = [UIButton buttonWithType:UIButtonTypeCustom];
btn_right.frame = CGRectMake(0, 0, 40, 30);
btn_right.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 2);
btn_right.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
[btn_right setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
btn_right.tag = 10;
//保证所有touch事件button的highlighted属性为NO,即可去除高亮效果
[btn_right addTarget:self action:@selector(preventFlicker:) forControlEvents:UIControlEventAllTouchEvents];
[btn_right addTarget:self action:@selector(rightBtnClick:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *rightItem = [[UIBarButtonItem alloc]initWithCustomView:btn_right];
self.navigationItem.rightBarButtonItem = rightItem;
}
-(void)rightBtnClick:(UIButton *)sender{
NSArray *viewControllers = self.navigationController.viewControllers;
if (viewControllers.count == 0) {
return;
}
if (self.navBtnAction) {//如果vc中调用了block回调就走自己的回调
self.navBtnAction(sender);
}else{//如果vc中没有调用block回调,直接返回到到上级页面
[self.navigationController popViewControllerAnimated:YES];
}
}
#pragma mark ------- create a image
-(UIImage *)createImageWithView:(UIView *)view{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, 0, [[UIScreen mainScreen] scale]);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return viewImage;
}
-(UIView *)getColorViewWithColor:(UIColor *)color{
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, navgationBarH)];
view.backgroundColor = color;
if (CGColorEqualToColor(color.CGColor, [UIColor clearColor].CGColor) || CGColorEqualToColor(color.CGColor, APPColor.CGColor)) {
}else{
view.layer.borderColor = ColorWithRGB(239, 239, 239).CGColor;
view.layer.borderWidth = 0.5;
view.layer.shadowColor=[ColorWithRGB(200, 200, 200) colorWithAlphaComponent:0.8].CGColor;
view.layer.shadowOffset=CGSizeMake(-4,-4);
view.layer.shadowOpacity=0.5;
view.layer.shadowRadius=4;
view.clipsToBounds = false;
}
return view;
}
#pragma mark ------- get nav bottom black line
-(UIImageView *)slnFindHairlineImageViewUnder:(UIView *)view {
if ([view isKindOfClass:UIImageView.class] && view.bounds.size.height <= 1.0){
return (UIImageView *)view;
}
for (UIView *subview in view.subviews) {
UIImageView *imageView = [self slnFindHairlineImageViewUnder:subview];
if (imageView) {
return imageView;
}
}
return nil;
}
#pragma mark ------- set nav background color
-(void)setNavigationBarBackgroundImageWithColor:(UIColor *)color{
[self.navigationController.navigationBar setBackgroundImage:[self createImageWithView:[self getColorViewWithColor:color]] forBarMetrics:UIBarMetricsDefault];
}
#pragma mark ------- show messgae on view of bottom
-(void)showMessageBottomWithText:(NSString *)text{
[CLToast showBottomWithText:NSLocalizedString(text, nil)];
}
#pragma mark ------- tableView pull and push action
-(void)addTableHeaderRefresh:(BOOL)headerRefresh tableFooterRefresh:(BOOL)footerRefresh{
if (headerRefresh) {
MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(reloadData)];
header.lastUpdatedTimeLabel.hidden = YES;
[header setTitle:@"拼命加载中..." forState:MJRefreshStateRefreshing];
[header setTitle:@"下拉刷新数据~" forState:MJRefreshStateIdle];
self.tableView.mj_header = header;
}
if (footerRefresh) {
MJRefreshAutoNormalFooter *footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)];
[footer setTitle:@"我是有底线的~" forState:MJRefreshStateNoMoreData];
[footer setTitle:@"拼命加载中..." forState:MJRefreshStateRefreshing];
[footer setTitle:@"上拉更多精彩~" forState:MJRefreshStateIdle];
footer.stateLabel.textColor = [UIColor lightGrayColor];
self.tableView.mj_footer = footer;
}
}
-(void)reloadData{
_pageNum = 1;
if (self.tableViewRefresh) {
self.tableViewRefresh(_pageNum);
}
}
-(void)loadMoreData{
_pageNum ++;
if (self.tableViewRefresh) {
self.tableViewRefresh(_pageNum);
}
}
-(void)tableViewEndRefresh{
[self.tableView.mj_header endRefreshing];
[self.tableView.mj_footer endRefreshing];
}
#pragma mark ------- custom hud
-(void)showCustomMessageViewWithText:(NSString *)text{
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
//修改样式,否则等待框背景色将为半透明
hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor;
//设置等待框背景色为黑色
hud.bezelView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.8];
//设置菊花框为白色
[UIActivityIndicatorView appearanceWhenContainedInInstancesOfClasses:@[[MBProgressHUD class]]].color = [UIColor whiteColor];
hud.label.text = NSLocalizedString(text, nil);
hud.label.textColor = [UIColor whiteColor];
hud.userInteractionEnabled = YES;
hud.mode = MBProgressHUDModeIndeterminate;
}
-(void)hiddenCustomMessageView{
[MBProgressHUD hideHUDForView:self.view animated:YES];
}
#pragma mark ------- custom activeIndicator
-(void)showCustomActiveIndicator{
_activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[self.view addSubview:_activityIndicator];
_activityIndicator.frame = CGRectMake((SCREEN_WIDTH - 99*WidthRatio)/2, (SCREEN_HEIGHT-99*WidthRatio)/2 - (navgationBarH + tabbarH)/2, 99*WidthRatio, 99*WidthRatio);
_activityIndicator.hidesWhenStopped = NO;
[_activityIndicator startAnimating];
}
-(void)hiddenCustomActiveIndicator{
[_activityIndicator stopAnimating];
[_activityIndicator removeFromSuperview];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
[[SDImageCache sharedImageCache] clearMemory];//清内存
[[SDImageCache sharedImageCache] clearDiskOnCompletion:nil];//清内存
// 1.取消正在下载的操作
[[SDWebImageManager sharedManager] cancelAll];
// 2.清除内存缓存
[[SDWebImageManager sharedManager].imageCache clearMemory];
}