UITableView 的前前后后

UITableView 可能是应用开发中最常用的一个控件了; 几乎任何一个应用都会需要显示一些列表的信息, 那就必然会用到显示列表的控件; 本文小田将以自己学习的角度尽可能详细分析UITableView, 并且尽量以非术语的方式和推理的方式来验证问题和知识点.

初体验

先看短代码


#import "ViewController.h"
@interface ViewController ()<UITableViewDataSource>
@property (weak, nonatomic) IBOutlet UITableView *mytableview;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  // Do any additional setup after loading the view, typically from a nib.
    self.mytableview.dataSource = self;
}

// 每一组有多少行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  return 10;
}

// 每一行显示的内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
  
  cell.textLabel.text = @"hello cell";
  
  return cell;
}
@end

如上是一个Controller 的完整实现(详细代码略), 代码中做了以下几件事情:

  1. ViewController准守了UITableViewDataSource协议;
  2. mtableviewdataSource属性赋值self;
  3. ViewController 实现了两个方法;

代码运行效果:

20170511149451690223861.png

图整个区域为tableview, 展示出了10条hello cell数据;从中我们可以直观感受到:

  1. numberOfRowsInSection 方法确定了列表的数据个数;
  2. cellForRowAtIndexPath 返回了每条数据的内容;

虽然这是tableview 最简单的使用, 也没有什么实际的应用场景, 但是它揭示了控件的基本运行逻辑, 从中我们能够看出控件到底是做什么用的, 并且为进一步学习和使用提供了一个很好的思路:

  1. 如何针对不同行返回不同的数据?
  2. 分组的数据应该如何显示?
  3. 每条数据的高度是怎么确定的?宽度是否可变?
  4. 每一行都会有个view来显示数据, 这个view是否可以重用?
  5. 如果每条数据中不只有一行文本,还想显示图片和副标题能不能办到?
  6. 更复杂的数据显示?
  7. 对数据的增删改怎么实现?
  8. 与用户的交互

我们以上述思路为提纲开始UITableView的解析.

一. 如何针对不同行返回不同的数据?

这应该是最基本的问题, 如果一个tableview不能根据行展示不同的数据,那么它可能就没存在的必要了. 从之前的代码中也能推测出, 我们应该在cellForRowAtIndexPath 方法中为每个indexPath 返回一个不同 cell. 于是有了如下代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    
        NSString * text = nil;
    switch (indexPath.row) {
        case 0:
            text = @"hello 0";
            break;
        ...
        ...
        case 9:
            text = @"hello 9";
            break;
        default:
            break;
    }
    cell.textLabel.text = text;
    return cell;
}

对于很多教程来说,上述代码都是是不推荐的,他们会说对于数据集我们应该单独存放,用的时候直接取值,这样将数据和使用放到一起是不符合规范的。 那为什么我还要写这样的代码呢?有两个原因:

  1. 代码可用!这是一个可用的代码,从其中我们能够更直接的理解cellForRowAtIndexPath的作用, 该方法通过一个indexPath来表示所处行, 并根据该值返回不同的数据!

  2. 代码本质! 所谓的规范是为了更好(没有bug, 包括功能bug和性能bug等)和更快(用时少)的实现一个需求,但规范并不能解决逻辑本质, 如果逻辑能够量化,代码中逻辑是守恒的, 准守规范不意味着不需要实现某些逻辑! 如上述代码中,如果准守规范将所有数据放入一个NSArray中,在用的时候通过下标取值,其逻辑与上述代码中的实现是相同的.

到此我们第一个问题的答案已经出现了, cellForRowAtIndexPath方法中,根据indexPath的值不同,返回不同的数据内容, 可以实现不同行返回不同的数据.

二.分组的数据应该如何显示?

直接上代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    NSString * text = [NSString stringWithFormat:@" hello in section %ld, row %ld", indexPath.section, indexPath.row];
    cell.textLabel.text = text;
    return cell;
}

indexPath中有 row 属性, 同时还有一个section属性,表示当前返回的cell 属于 第section组的第row行. 可以根据这个值来确定当前的数据内容.

那么如何知道有多少组(section) 每个组有多少行数据呢?

// 返回多少组
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 2;
}
// 返回对应section 中有多少行 row
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    switch (section) {
        case 0:
            return 3;
        case 1:
            return 2;
        default:
            break;
    }
    return 0;
}

好了,我们现在可以显示多个组的数据了, 当我们想为不同的组添加一个标题时 可以使用titleForHeaderInSection 或者viewForHeaderInSection 方法:

// 设置纯文本 的section header
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return [NSString stringWithFormat:@"section header at %ld", section];
}

//设置section view, 拜托系统header限制,自定义样式;
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UIView* myView = [[UIView alloc] initWithFrame:CGRectMake(10, 0, 300, 50)];
    myView.backgroundColor = [UIColor colorWithRed:0.10 green:0.68 blue:0.94 alpha:0.7];
    UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 300, 22)];
    titleLabel.textColor=[UIColor whiteColor];
    titleLabel.backgroundColor = [UIColor clearColor];
    titleLabel.text=[NSString stringWithFormat:@"section header at %ld", section];
    [myView addSubview:titleLabel];
    
    return myView;
}

经测试如上两个设置section header 的方法不能共存, 当同时实现时viewForHeaderInSection的优先显示.

最后, 我们会发现viewForHeaderInSection中没有办法设置section header 的高度,即便返回的view 设置了高度也没有效果, 这是我们需要修改tableviewsectionHeaderHeight 属性.

sectionHeaderHeight 属性是属于tableview的, 不会根据section 的不同而不同, 因此只需要在数据加载之前设置一次即可!

viewForHeaderInSection 中添加tableView.sectionHeaderHeight = 100; 时, 代码是没有效果的, 因此可以推断 tableview在加载数据过程中 section header的大小已经固定了, 再设置是不起作用的.

tableview 针对不同Section 返回不同头部高度的方法heightForHeaderInSection

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    // 根据section 返回不同的高度
    return 50*section +50;
}

经测试同时设置sectionHeaderHeight属性和实现heightForHeaderInSection方法, 会以heightForHeaderInSection方法返回的高度为准.

未完待续...

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

推荐阅读更多精彩内容