先解释下题目,好比下面这个设置页面,里面的内容会根据用户身份、权限等等看到不一样的可设置内容:3d
咱们先假设最简单的状况,形成左右两边差别的缘由彻底就是因为一个变量的值的不一样致使,isMyHome,若是为YES,则最终看到左边的效果,若是为NO,则最终看到右边的效果。代理
问题来了,你会如何实现UITableView的各类delegate?code
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { if (self.isMyHome) { return 3; } else { return 4; } } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (self.isMyHome) { // 有3个section switch (section) { case 0: return 4; break; case 1: return 1; break; case 2: return 2; break; default: break; } } else { switch (section) { case 0: return 2; break; case 1: return 1; break; case 2: return 1; break; case 3: return 1; break; default: break; } } return 0; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (self.isMyHome) { if (indexPath.section == 2 && indexPath.row == 0) { // 有一个row稍微有点高 return 70; } else { return 40; } } else { return 40; } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = ni; // ...真的不想写了快吐了,这才一个变量的区别 return cell; }
以上的写法有两个大问题:blog
这才一个变量啊,试想实际项目中,每每不少变量综合决定了哪一个row显示、那个row不显示、row长什么样。想一想下,若是有一天产品经理说,去掉“宝宝信息”这行,我以为你就要疯了,要把index所有都减一,每一个代理都要检查一遍是否对得上index。ci
因此,这两个问题,致使的后果:难实现、容易出bug、不易维护。产品
既然上面的实现这么很差,该怎么实现呢?其实就是逐一解决上面提到的两个问题。it
对于1,其实形成问题的本质缘由是:在任什么时候候,把一个row应该显示与否、以及长什么样子、row对应的index是什么, 这些问题都融合在一块儿了,将问题复杂程度一下提高了不少。对于2,都使用枚举就行了,避免
这里提出解决办法:io
这样,“section、row的个数(index)”、“section、row是否显示”、“row长什么样”,这三个问题就分散到了4个delegate中:table
代码长这样:变量
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 4; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { switch (section) { case SectionOne: return 4; break; case SectionTwo: return 1; break; case SectionThree: return 2; break; case SectionFour: return 1; break; default: break; } } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 0) { switch (indexPath.row) { case SectionOneRowOne: return 40 break; case SectionOneRowTwo: return self.isMyHome ? 40 : 0; break; case SectionOneRowThree: return self.isMyHome ? 40 : 0; break; case SectionOneRowFour: return 40 break; default: break; } } else if (indexPath.section == 1) { return 40; } else if (indexPath.section == 2) { switch (indexPath.row) { case SectionThreeRowOne: return self.isMyHome ? 70 : 0; break; case SectionThreeRowTwo: return 40; break; default: break; } } else { return self.isMyHome ? 0 : 40; } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 对于每一个cell,配置内容就行了,index都是固定的 }
若是产品经理说,删除“宝宝信息”这行吧,那么咱们只要把heightForRowAtIndexPath,相应高度改成0就行了,以后产品经理反悔还能够直接改回来,就算想彻底删了,也很省事,不容易出bug。
核心思想,其实就是,UITableView的几个delegate,分别只解决一个问题,不要把问题都揉在一块儿,让代码变得复杂
假如要去掉一整个section怎么办,好比产品经理说,不要“我在小家的称呼”这行了。
固然,没问题,咱们直接把heightForRowAtIndexPath里这行,改成0就行了嘛!
等等,虽然这行没了,可是前两个section之间的间隙,有可能会变大,由于只是设置了height为0而已,seciton还在嘛。这种状况怎么办?
不用担忧,只要设置section的间隙,使用相似这种方式去设置,响应的改变section header的值,就行了~
其实,这种设置section的间隙的方式,也是咱们常用的嘛,基本都不太用系统默认的间隙。
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return section == 0 ? 0 : 8; } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { if (section == 0) { return [UIView new]; } UIView *sectionHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 8)]; sectionHeader.backgroundColor = [UIColor clearColor]; return sectionHeader; }