iOS 開發小技巧---baseViewcontroller
摘要:
還在為每個檢視控制都要自定義導航欄按鈕而煩躁嗎?還在為每個檢視控制器的列表都要新增一遍上拉重新整理下拉載入而焦心嗎?還在為每個列表新增空白提示而煩惱嗎?不要怕,你需要一個基類,一個救你於水火的VC的基類!
當你看到一個VC中幾千行程式碼的時候你是絕望的,崩潰的!介面那些每個介面都要...
還在為每個檢視控制都要自定義導航欄按鈕而煩躁嗎?還在為每個檢視控制器的列表都要新增一遍上拉重新整理下拉載入而焦心嗎?還在為每個列表新增空白提示而煩惱嗎?不要怕,你需要一個基類,一個救你於水火的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 = [selfslnFindHairlineImageViewUnder: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]; }