将界面的拼装抽象到专门的类中
在Brower/Server系统中浏览器承担着view容器的功能,而在iOS里是UIViewController承担的,UIViewController中自带的那个view,它的主要任务就是作为一个容器。
在 Controller 中把一个个 UILabel ,UIButton,UITextField 往 self.view 上用 addSubView 方法放。视图复杂时候,这些代码会非常多且杂乱。
我们可以创建一个View视图来专门来负责这些控件的拼装。不过事件的回调需要先接管然后回调给Controller。为避免麻烦简单页面可以分出单独方法来做这件事,或者子视图控件全部使用懒加载,一个方法里只做[self.view addSubview:view]
操作即可。如果使用xib写界面的可忽略这一点。
数据存取抽象到单独的类中
这里的数据存取包括网络请求,可以称这种方式为MVCS。从概念上来说,它拆分的部分是Model部分,拆出来一个Store。这个Store专门负责数据存取。但从实际操作的角度上讲,它拆开的是Controller。
这算是瘦Model的一种方案,瘦Model只是专门用于表达数据,然后存储、数据处理都交给外面的来做。MVCS使用的前提是,它假设了你是瘦Model,同时数据的存储和处理都在Controller去做。所以对应到MVCS,它在一开始就是拆分的Controller。因为Controller做了数据存储的事情,就会变得非常庞大,那么就把Controller专门负责存取数据的那部分抽离出来,交给另一个对象去做,这个对象就是Store。这么调整之后,整个结构也就变成了真正意义上的MVCS。
我们网络请求可以交给单独的一个类来完成,直接交付model给控制层使用。这样做的好处:
- 将网络请求与第三方库依赖隔离,方便以后更换底层的网络库。
- 方便在基类中处理一些公共逻辑
分理出 UITableView 的 Data Source
将 UITableView 的 Data Source 分离到另外一个类中。
将数据获取和转换的逻辑分别到另外一个类中。网络请求与数据的封装放在另外类中
将拼装控件的逻辑,分离到另外一个类中。将子视图添加到一个view上,这个view通过代理,来通知viewController处理事件。下面简单示例:
@interface ArrayDataSource ()
@property(nonatomic, strong) NSArray* dataSource;/**< array */
@property(nonatomic, copy) NSString* cellIdentifier;/**< cellIdentifier */
@property(nonatomic, copy) TableViewCellConfigureBlock configureCellBlock;/**< block */
@end
@implementation ArrayDataSource
- (id)initWithItems:(NSArray *)dataSource cellIdentifier:(NSString *)aCellIdentifier configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock {
self = [super init];
if (self) {
self.dataSource = dataSource;
self.cellIdentifier = aCellIdentifier;
//block回调给controller填充数据
self.configureCellBlock = aConfigureCellBlock;
}
return self;
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.dataSource.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier];
id item = _dataSource[indexPath.row];
self.configureCellBlock(cell, item);//回调给controller填充数据
return cell;
}
@end
一些复杂操作可以继承该类,特殊处理。
使用胖model
胖Model包含了部分弱业务逻辑。胖Model要达到的目的是,Controller从胖Model这里拿到数据之后,不用额外做操作或者只要做非常少的操作,就能够将数据直接应用在View上。胖model也做数据的拼装,甚至与网络请求,model与请求往往是一一对应的。