iOS開發(fā)之讓控制器變得更輕量級

為何要輕量級

通常,項目中有些 viewControllers 非常臃腫,把一些控制器不需要知道的代碼和邏輯全都放在了控制器的文件中,小則好幾百行大則上千,代碼風(fēng)格飄忽不定,前邏輯后數(shù)據(jù)處理,讓擦屁股的人苦不堪言,"尼瑪,這都是什么玩意兒!!!".今天我們來研究如何把這些代碼搬到合適的位置,讓你的 viewControllers 從此告別"脂肪",挺起雙峰.

如何變得輕量級

1. 剝?nèi)?UITableViewDataSource 代理方法

項目中很多地方會用到 tableView 來展示數(shù)據(jù), 同樣 viewController 會實現(xiàn) UITableViewDataSource 的以下代理方法


- (id)itemAtIndexPath:(NSIndexPath *)indexPath{
    return _items[indexPath.row];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return _items.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
    FYBaseCell *cell = (FYBaseCell *)[tableView dequeueReusableCellWithIdentifier:_cellIdentifier];
    
    if (_cellType == kFYCellTypeDefault) {
        if (!cell) {
            cell = [[DemoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:_cellIdentifier];
        }
    }
    
    id item = [self itemAtIndexPath:indexPath];
    [cell  configureCellContentWithItem:item];
    return cell;
}

這些 dataSource 方法可以不用在 viewControllers 中實現(xiàn),因為 viewControllers 并不關(guān)心 cell 如何展示數(shù)據(jù),所以我們可以抽象出一個 FYDataSource 類出來,實現(xiàn) UITableViewDataSource 代理方法


@interface FYDataSource()

@property (nonatomic, copy)         NSString *cellIdentifier;
@property (nonatomic, assign)       kFYCellType cellType;

@end
- (id)itemAtIndexPath:(NSIndexPath *)indexPath{
    return _items[indexPath.row];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return _items.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
    FYBaseCell *cell = (FYBaseCell *)[tableView dequeueReusableCellWithIdentifier:_cellIdentifier];
    
    if (_cellType == kFYCellTypeDefault) {
        if (!cell) {
            cell = [[DemoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:_cellIdentifier];
        }
    }
    
    id item = [self itemAtIndexPath:indexPath];
    [cell  configureCellContentWithItem:item];
    return cell;
}

我們再給這個抽象類添加一個實例方法,下面貼出 FYDataSource 這個類的頭文件代碼

// FYDataSource.h 文件的代碼

typedef NS_ENUM(NSInteger, kFYCellType){
    kFYCellTypeDefault = 0,
};

@interface FYDataSource : NSObject <UITableViewDataSource>
@property (nonatomic, strong)       NSArray *items;  //模型數(shù)組

/**
 *  創(chuàng)建一個FYDataSource對象
 *
 *  @param items          模型數(shù)組
 *  @param cellIdentifier cell的緩存標(biāo)識符
 *  @param cellType       cell類型
 *
 *  @return 實例好的FYDataSource對象
 */
- (instancetype)initWithItems:(NSArray *)items cellIdentifier:(NSString *)cellIdentifier cellType:(kFYCellType)cellType;

@end

*這樣就成功剝離了 UITableViewDataSource 的代理方法,并且多了 FYDataSource 這個工具類, ?可以復(fù)用, 與此同時你可以實現(xiàn)其它 UITableViewDataSource 代理方法,比如: *

tableView:commitEditingStyle:forRowAtIndexPath:

同樣的方法你也可以使用在 UICollectionViewDataSource 這個類上,趕緊給你的 viewControllers 瘦身吧!

*2. 剝?nèi)?UITableViewDelegate 方法 *

*同樣 UITableViewDelegate 的代理方法在控制器中也占據(jù)這不少的篇幅,我們也可以給它剝離出來,這里我把代理方法在 FYDataSource 中,同時通過代理傳出一些必要參數(shù)給控制器,代碼如下: *

//  .h 文件

@protocol FYDataSourceDelegate <NSObject>

@optional
/**
 *  點擊cell的代理方法,傳出對應(yīng)的item模型以及對應(yīng)的tablview
 *
 *  @param item      對應(yīng)的item
 *  @param tableView 對應(yīng)的tablview
 */
- (void)didSelectedCellWithItem:(id)item tableView:(UITableView *)tableView;

- (CGFloat)heightForHeaderInSection:(NSInteger)section tableView:(UITableView *)tableView;
- (UIView *)viewForHeaderInSection:(NSInteger)section tableView:(UITableView *)tableView;

- (CGFloat)heightForFooterInSection:(NSInteger)section tableView:(UITableView *)tableView;
- (UIView *)viewForFooterInSection:(NSInteger)section tableView:(UITableView *)tableView;

- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView;

@end
// .m 文件中的實現(xiàn)
#pragma mark
#pragma mark - UITableViewDelegate

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    
    id item = [self itemAtIndexPath:indexPath];
    return [_baseCell configureCellHeightWithItem:item];
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    
    id item = [self itemAtIndexPath:indexPath];
    
    FYBaseCell *cell = (FYBaseCell *)[self tableView:tableView cellForRowAtIndexPath:indexPath];
    [cell didSelectedWithItem:item];
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectedCellWithItem:tableView:)]) {
        [self.delegate didSelectedCellWithItem:item tableView:tableView];
    }
    
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(heightForHeaderInSection:tableView:)]) {
        return [self.delegate heightForFooterInSection:section tableView:tableView];
    }
    
    return 1.0f;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(heightForFooterInSection:tableView:)]) {
        return [self.delegate heightForFooterInSection:section tableView:tableView];
    }
    
    return 1.0f;
}

- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(viewForHeaderInSection:tableView:)]) {
        return [self.delegate viewForHeaderInSection:section tableView:tableView];
    }
    
    return nil;
}

- (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(viewForFooterInSection:tableView:)]) {
        return [self.delegate viewForFooterInSection:section tableView:tableView];
    }
    
    return nil;
}

* 3. 將某些邏輯移動到 Model 中 *

下面有一個例子,在控制器中給 user 屬性賦值一個列表屬性:

- (void)loadPriorities {
    NSDate* now = [NSDate date];
    NSString* formatString = @"startDate <= %@ AND endDate >= %@";
    NSPredicate* predicate = [NSPredicate predicateWithFormat:formatString, now, now];
    NSSet* priorities = [self.user.priorities filteredSetUsingPredicate:predicate];
    self.priorities = [priorities allObjects];
}

如果我們把這些邏輯交給 ?User 來處理,控制器就會變得清潔了:

- (void)loadPriorities {
    self.priorities = [self.user currentPriorities];
}

邏輯我們通過給 User 創(chuàng)建擴(kuò)展 User+Extensions.m 來處理:

- (NSArray*)currentPriorities {
    NSDate* now = [NSDate date];
    NSString* formatString = @"startDate <= %@ AND endDate >= %@";
    NSPredicate* predicate = [NSPredicate predicateWithFormat:formatString, now, now];
    return [[self.priorities filteredSetUsingPredicate:predicate] allObjects];
}

擴(kuò)展閱讀

Lighter View Controller
Clean Table View Code

總結(jié)

給控制器瘦身的方法還有很多,在這里就不一一說了,擴(kuò)展閱讀 介紹了不少,項目中如果用到的話可以節(jié)省不少開發(fā)時間,另外希望各位多多分享,共同進(jìn)步.
demo 地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子伞广,更是在濱河造成了極大的恐慌省有,老刑警劉巖券册,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)苦丁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來物臂,“玉大人旺拉,你說我怎么就攤上這事产上。” “怎么了蛾狗?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵蒂秘,是天一觀的道長。 經(jīng)常有香客問我淘太,道長,這世上最難降的妖魔是什么规丽? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任蒲牧,我火速辦了婚禮,結(jié)果婚禮上赌莺,老公的妹妹穿的比我還像新娘冰抢。我一直安慰自己,他們只是感情好艘狭,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布挎扰。 她就那樣靜靜地躺著,像睡著了一般巢音。 火紅的嫁衣襯著肌膚如雪遵倦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天官撼,我揣著相機(jī)與錄音梧躺,去河邊找鬼。 笑死傲绣,一個胖子當(dāng)著我的面吹牛掠哥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播秃诵,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼续搀,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了菠净?” 一聲冷哼從身側(cè)響起禁舷,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嗤练,沒想到半個月后榛了,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡煞抬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年霜大,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片革答。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡战坤,死狀恐怖曙强,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情途茫,我是刑警寧澤碟嘴,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站囊卜,受9級特大地震影響娜扇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜栅组,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一雀瓢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧玉掸,春花似錦刃麸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至啊易,卻和暖如春吁伺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背认罩。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工箱蝠, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人垦垂。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓宦搬,卻偏偏與公主長得像,于是被迫代替她去往敵國和親劫拗。 傳聞我的和親對象是個殘疾皇子间校,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

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

  • 翻譯自“View Controller Programming Guide for iOS”。 1 彈出視圖控制器...
    lakerszhy閱讀 3,541評論 2 20
  • iOS 實戰(zhàn)開發(fā)課程筆記 本貼旨在作為對極客班 《iOS 開發(fā)實戰(zhàn)》第五期期課程視頻重新學(xué)習(xí)的筆記页慷。目標(biāo)是建立一個...
    黃穆斌閱讀 3,011評論 12 57
  • 八月桂花撲面香 街頭巷尾遍地黃 沁人心脾年年有 歲月悠悠黯黯傷
    雙魚座cy閱讀 232評論 3 6
  • 當(dāng)車子七拐八拐的駛進(jìn)墓地大門的時候憔足,我們還在分享最近身邊發(fā)生的有趣的事情,妄圖將慢慢滲透進(jìn)來的悲傷氣息隔...
    沈聿閱讀 276評論 0 0