iOS開發(fā)技巧 - UIViewController 基類設(shè)計(jì)

在項(xiàng)目開發(fā)中,所有控制器里面大概都有共同的屬性,比如背景色、導(dǎo)航欄、tarBar 的設(shè)置等等,這時(shí)我們一般都會(huì)設(shè)計(jì)出來一個(gè) UIViewController 的基類,通常叫做 baseViewControllerrootViewController,在這個(gè)類里面設(shè)置所有控制器的共同的屬性,然后項(xiàng)目中所有的控制器再繼承自這個(gè)類。

一般來說這種基類控制器里面需要做的操作有以下幾個(gè):
  • 為 APP 設(shè)置統(tǒng)一的背景色
  • 設(shè)置是否允許控制器自動(dòng)調(diào)整高度(一般是 NO)
  • 自定義導(dǎo)航欄返回按鈕
  • 重新布局視圖大小,及時(shí)更新視圖的 frame

當(dāng)然還有其它的一些,畢竟這和項(xiàng)目的具體需求息息相關(guān),因此還要因項(xiàng)目而異。我這里主要就列出基類控制器中基本的常用的一些需求,和大家分享下,希望能幫到需要的人,少走彎路;另外文章如果有不足之處,也希望各位同行能多多的交流指點(diǎn)。


</br>

UIViewController 基類控制器設(shè)計(jì)步驟

首先創(chuàng)建一個(gè) UIViewController 類,命名為 NNBaseViewController
接著在 NNBaseViewController.m中做一些操作

1.設(shè)置應(yīng)用的統(tǒng)一背景色

    // 設(shè)置應(yīng)用的背景色
    self.view.backgroundColor = [UIColor lightGrayColor];

2.將 automaticallyAdjustsScrollViewInsets 設(shè)置為NO,不然視圖會(huì)下移64像素

// 不允許 viewController 自動(dòng)調(diào)整,我們自己布局;如果設(shè)置為YES,視圖會(huì)自動(dòng)下移 64 像素
    self.automaticallyAdjustsScrollViewInsets = NO;

3.有時(shí)候系統(tǒng)的返回按鈕不符合應(yīng)用的風(fēng)格,所以就需要重寫導(dǎo)航欄上的返回按鈕

#pragma mark - 自定義返回按鈕
- (void)setupLeftBarButton {
    // 自定義 leftBarButtonItem ,UIImageRenderingModeAlwaysOriginal 防止圖片被渲染
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]
                                             initWithImage:[[UIImage imageNamed:@"Back-藍(lán)"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
                                             style:UIBarButtonItemStylePlain
                                             target:self
                                             action:@selector(leftBarButtonClick)];
    // 防止返回手勢失效
    self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
}

#pragma mark - 返回按鈕的點(diǎn)擊事件
- (void)leftBarButtonClick {
    [self.navigationController popViewControllerAnimated:YES];
}

當(dāng)然這里需要判斷一下,不然首層控制器的導(dǎo)航欄上也會(huì)被設(shè)置上返回按鈕 leftBarButtonItem,我是在 - (void)viewDidLoad 方法中判斷的。

    // 判斷是否有上級頁面,有的話再調(diào)用
    if ([self.navigationController.viewControllers indexOfObject:self] > 0) {
        [self setupLeftBarButton];
    }

4.接下來我們一起設(shè)置下 View 中視圖的布局,根據(jù)視圖中控件的最大的 Y 值和最大的 X 值調(diào)整 Viewframe 。這個(gè)主要用在視圖中控件比較多的時(shí)候,也需要具體分析,比如有時(shí)候應(yīng)用中全是 UITableView,那么就不需要設(shè)置了,因?yàn)?UITableView 可以根據(jù) cell 自動(dòng)調(diào)整 frame。不過也有用到的時(shí)候,比如應(yīng)用中需要計(jì)算高度的類有很多,那么就可以用這個(gè)統(tǒng)一設(shè)置,主要還是看項(xiàng)目需求。另外注意這個(gè)方法要放在 - (void)viewWillAppear:(BOOL)animated中。

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    CGFloat baseViewHeight = 0;
    CGFloat baseViewWidth = 0;
    NSArray *subViews = self.baseView.subviews;
    
    // 遍歷視圖中的所有控件,求出最大的Y值和最大的X值
    for (UIView *view in subViews) {
        if (CGRectGetMaxY(view.frame) > baseViewHeight) {
            baseViewHeight = CGRectGetMaxY(view.frame);
        }
        if (CGRectGetMaxX(view.frame) > baseViewWidth) {
            baseViewWidth = CGRectGetMaxX(view.frame);
        }
    }
    
    // 三目運(yùn)算方法求出最大的寬是否大于屏幕寬,以及最大的高是否大于屏幕高
    CGFloat NNHeight = baseViewHeight > NNBaseViewSizeHeight ? baseViewHeight:NNBaseViewSizeHeight;
    CGFloat NNWidth = baseViewWidth > NNBaseViewSizeWidth ? baseViewWidth:NNBaseViewSizeWidth;

    self.baseView.contentSize = CGSizeMake(NNWidth, NNHeight);
}

上面代碼塊中用到了一個(gè)屬性 baseViewbaseView 屬于 UIScrollView 類,相當(dāng)于一個(gè)子視圖容器,所有繼承自 NNBaseViewController 的控制器都應(yīng)該把子視圖添加到 baseView上,這樣才能更新它的 frame

#import <UIKit/UIKit.h>

@interface NNBaseViewController : UIViewController

/** 子視圖容器 */
@property (nonatomic, strong) UIScrollView *baseView;

@end

另外別忘了在 - (void)viewDidLoad 這個(gè)方法中創(chuàng)建baseView并設(shè)置它的屬性。

    self.baseView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 64, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 64)];
    // 是否反彈
    self.baseView.bounces = NO;
    // 是否顯示滾動(dòng)指示器
    self.baseView.showsVerticalScrollIndicator = NO;
    self.baseView.showsHorizontalScrollIndicator = NO;
    
    [self.view addSubview:self.baseView];
    self.baseView.contentSize = NNContentSize;
    

上面便是一個(gè)基本的 UIViewController 的基類,具體還是要根據(jù)項(xiàng)目的需要來設(shè)計(jì)。



</br>

接下來是完整的代碼:

NNBaseViewController.h
#import <UIKit/UIKit.h>

@interface NNBaseViewController : UIViewController

/** 子視圖容器 */
@property (nonatomic, strong) UIScrollView *baseView;

@end
NNBaseViewController.m
#import "NNBaseViewController.h"

#define NNBaseViewSize self.baseView.bounds.size
#define NNBaseViewSizeHeight self.baseView.bounds.size.height
#define NNBaseViewSizeWidth self.baseView.bounds.size.width

@interface NNBaseViewController ()

@end

@implementation NNBaseViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupViews];
    // 判斷是否有上級頁面,有的話再調(diào)用
    if ([self.navigationController.viewControllers indexOfObject:self] > 0) {
        [self setupLeftBarButton];
    }
}

- (void)setupViews {
    // 設(shè)置應(yīng)用的背景色
    self.view.backgroundColor = [UIColor lightGrayColor];
    // 不允許 viewController 自動(dòng)調(diào)整,我們自己布局;如果設(shè)置為YES,視圖會(huì)自動(dòng)下移 64 像素
    self.automaticallyAdjustsScrollViewInsets = NO;
    self.baseView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 64, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 64)];
    // 是否反彈
    self.baseView.bounces = NO;
    // 是否顯示滾動(dòng)指示器
    self.baseView.showsVerticalScrollIndicator = NO;
    self.baseView.showsHorizontalScrollIndicator = NO;
    
    [self.view addSubview:self.baseView];
    self.baseView.contentSize = NNBaseViewSize;
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    CGFloat baseViewHeight = 0;
    CGFloat baseViewWidth = 0;
    NSArray *subViews = self.baseView.subviews;
    
    // 遍歷視圖中的所有控件,求出最大的Y值和最大的X值
    for (UIView *view in subViews) {
        if (CGRectGetMaxY(view.frame) > baseViewHeight) {
            baseViewHeight = CGRectGetMaxY(view.frame);
        }
        if (CGRectGetMaxX(view.frame) > baseViewWidth) {
            baseViewWidth = CGRectGetMaxX(view.frame);
        }
    }
    
    // 三目運(yùn)算方法求出最大的寬和最大的高
    CGFloat NNHeight = baseViewHeight > NNBaseViewSizeHeight ? baseViewHeight:NNBaseViewSizeHeight;
    CGFloat NNWidth = baseViewWidth > NNBaseViewSizeWidth ? baseViewWidth:NNBaseViewSizeWidth;

    self.baseView.contentSize = CGSizeMake(NNWidth, NNHeight);
}

#pragma mark - 自定義返回按鈕
- (void)setupLeftBarButton {
    // 自定義 leftBarButtonItem ,UIImageRenderingModeAlwaysOriginal 防止圖片被渲染
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]
                                             initWithImage:[[UIImage imageNamed:@"Back-藍(lán)"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
                                             style:UIBarButtonItemStylePlain
                                             target:self
                                             action:@selector(leftBarButtonClick)];
    // 防止返回手勢失效
    self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
}

#pragma mark - 返回按鈕的點(diǎn)擊事件
- (void)leftBarButtonClick {
    [self.navigationController popViewControllerAnimated:YES];
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容