iOS开发之让控制器变得更轻量级

为何要轻量级

通常,项目中有些 viewControllers 非常臃肿,把一些控制器不需要知道的代码和逻辑全都放在了控制器的文件中,小则好几百行大则上千,代码风格飘忽不定,前逻辑后数据处理,让擦屁股的人苦不堪言,"尼玛,这都是什么玩意儿!!!".今天我们来研究如何把这些代码搬到合适的位置,让你的 viewControllers 从此告别"脂肪",挺起双峰.

如何变得轻量级

1. 剥去 UITableViewDataSource 代理方法

项目中很多地方会用到 tableView 来展示数据, 同样 viewController 会实现 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 中实现,因为 viewControllers 并不关心 cell 如何展示数据,所以我们可以抽象出一个 FYDataSource 类出来,实现 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;  //模型数组

/**
 *  创建一个FYDataSource对象
 *
 *  @param items          模型数组
 *  @param cellIdentifier cell的缓存标识符
 *  @param cellType       cell类型
 *
 *  @return 实例好的FYDataSource对象
 */
- (instancetype)initWithItems:(NSArray *)items cellIdentifier:(NSString *)cellIdentifier cellType:(kFYCellType)cellType;

@end

*这样就成功剥离了 UITableViewDataSource 的代理方法,并且多了 FYDataSource 这个工具类, �可以复用, 与此同时你可以实现其它 UITableViewDataSource 代理方法,比如: *

tableView:commitEditingStyle:forRowAtIndexPath:

同样的方法你也可以使用在 UICollectionViewDataSource 这个类上,赶紧给你的 viewControllers 瘦身吧!

*2. 剥去 UITableViewDelegate 方法 *

*同样 UITableViewDelegate 的代理方法在控制器中也占据这不少的篇幅,我们也可以给它剥离出来,这里我把代理方法在 FYDataSource 中,同时通过代理传出一些必要参数给控制器,代码如下: *

//  .h 文件

@protocol FYDataSourceDelegate <NSObject>

@optional
/**
 *  点击cell的代理方法,传出对应的item模型以及对应的tablview
 *
 *  @param item      对应的item
 *  @param tableView 对应的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 文件中的实现
#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 创建扩展 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];
}

扩展阅读

Lighter View Controller
Clean Table View Code

总结

给控制器瘦身的方法还有很多,在这里就不一一说了,扩展阅读 介绍了不少,项目中如果用到的话可以节省不少开发时间,另外希望各位多多分享,共同进步.
demo 地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容

  • 翻译自“View Controller Programming Guide for iOS”。 1 弹出视图控制器...
    lakerszhy阅读 3,424评论 2 20
  • iOS 实战开发课程笔记 本贴旨在作为对极客班 《iOS 开发实战》第五期期课程视频重新学习的笔记。目标是建立一个...
    黄穆斌阅读 2,981评论 12 57
  • 八月桂花扑面香 街头巷尾遍地黄 沁人心脾年年有 岁月悠悠黯黯伤
    双鱼座cy阅读 223评论 3 6
  • 当车子七拐八拐的驶进墓地大门的时候,我们还在分享最近身边发生的有趣的事情,妄图将慢慢渗透进来的悲伤气息隔...
    沈聿阅读 267评论 0 0