UITableView

UITableView继承于UIScrollView,可以滚动。 UITableView的每一条数据对应的单元格叫做Cell,是UITableViewCell一个对象,继承于UIView。 UITableView可以分区显⽰示, 每一个分区称为section, 每一⾏称为row, 编号都从0开始。 系统提供了一个专门的类来整合section和row,叫做NSIndexPath。

//创建UITableView

   UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.boundsstyle:UITableViewStylePlain];    

[self.view addSubview:tableView];    

[tableView release];

//UITableView的样式枚举

  // UITableView的初始化⽅方法包含⼀一个UITableViewStyle类型的参数 这是⼀一个枚举类型    

typedef NS_ENUM(NSInteger, UITableViewStyle) 

{        UITableViewStylePlain,        UITableViewStyleGrouped    };

//UITableView的相关属性

   //rowHeight        行高

   //separtorStyle    分隔线样式

   //separtorColor    分隔线颜⾊

   //tableHeaderView  UITableView的置顶视图

   //tableFooterView  UITableView的置底视图

//UITableView中有两个重要的属性:

   @property (nonatomic, weak, nullable) id     dataSource;

    //dataSource 显示数据相关的代理    @property (nonatomic, weak, nullable) id     delegate;

    //delegate   视图操作相关的代理


//UITableView代理的实现代码

   1.签订UITableView协议    

   2.设置当前的ViewController为 UITableView

//UITableViewCell

   //UITableView的每一个单元格是UITableViewCell类的对 UITableViewCell默认提供了3个视图属性:

   UIImageView *imageView  图片视图

   UILabel *textLabel      标题视图

   UILabel *detailTextLabel 副标题视图

//UITableView重用cell的代码流程

   1. 在创建UITableView之后,需要注册一个cell类,当重用池中没有 cell的时候,系统可以自动创建cell。 相关方法:    - (void)registerClass:(Class)cellClass forCellReuseIdentifier: (NSString *)identifier;    2.系统提供了一个获取重⽤用池中cell的⽅方法(需要提供一个重用标 识):    - (UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier;

//UITableViewController

   UITableViewController是继承于UITableViewController中的一个 类,只不过⽐比UITableViewController中多了一个属性tableView。 即:UITableViewController是一个自带table的视图控制器。

 一:UITableViewController继承自UITableViewController,自带 一个􏰅ableVie􏰁   

 二:[self.view]不是UIView而是UITableView   

 三:datasource和delegate默认都是 self(UITableViewController)    

 四:开发中只需要建立UITableViewController子类

UITableView   需要签订两个协议,一个是datasource,一个是delegate

dataSource:

UITableViewDataSource类型

主要为UITableView提供显示用的数据(UITableViewCell),指定UITableViewCell支持的编辑操作类型(insert,delete和reordering),并根据用户的操作进行相应的数据更新操作,如果数据没有更具操作进行正确的更新,可能会导致显示异常,甚至crush。

//调用数据源的下面方法得知一共有多少组数据

- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView;

//调用数据源的下面方法得知每一组有多少行数据

- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section;

//调用数据源的下面方法得知每一行显示什么内容

- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath;

delegate:

UITableViewDelegate类型,主要提供一些可选的方法,用来控制tableView的选择、指定section的头和尾的显示以及协助完成cell的删除和排序等功能。

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

这里注意:如果不是cell有不同高度的需求,在设置cell的高度上,最好不要用这个,直接在创建tableview的时候,设置rowHeight即可。

accessoryType属性:

辅助指示视图的作用是显示一个表示动作的图标,可以通过设置UITableViewCell的accessoryType(其属性)来显示,默认是UITableViewCellAccessoryNone(不显示辅助指示视图),其他值如下:

UITableViewCellAccessoryDisclosureIndicator       箭头

UITableViewCellAccessoryDetailDisclosureButton 按钮+箭头

UITableViewCellAccessoryCheckmark                       对勾

UITableViewCellAccessoryNone                                       没有

UITableViewCellAccessoryDetaiButton                          叹号按钮

UITableViewCellStyle四种样式

cell的重用原理

iOS设备的内存有限,如果用UITableView显示成千上万条数据,就需要成千上万个UITableViewCell对象的话,那将会耗尽iOS设备的内存。要解决该问题,需要重用UITableViewCell对象

原理:

当滑动列表时,部分cell会移处窗口,UITableView会将窗口外的UITableViewCell放入一个对象池中,等待重用。当UITableView要求dataSource返回UITableViewCell时,dataSource会先查看这个对象池,如果池中有未使用的UITableViewCell,dataSource会用新的数据配置这个UITableViewCell,然后返回给UITableView,重新显示到窗口中,从而避免创建新对象

注意:

有时候需要自定义UITableViewCell,而且每一行用的不一定是同一种cell,所以一个UITableView可能拥有不同类型的UITableViewCell。对象池中也会有很多不同类型的UITableViewCell,那么在UITableView重用cell时可能会得到错误类型的UITableViewCell

解决方案:

UITableViewCell有个NSString *reuseIdentifier属性,可以在初始化UITableViewCell的时候传入一个特定的字符串标识来设置reuseIdentifier(一般用UITableViewCell的类名)。当UITableView要求dataSource返回UITableViewCell时,先通过一个字符串标识到对象池中查找对应类型的UITableViewCell对象,如果有,就重用,如果没有,就传入这个字符串标识来初始化一个UITableViewCell对象

cell的重用代码

方法一:

- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath

{//注意:重用机制是根据相同的标识符来重用cell,标识符不同的cell不能彼此重用

  1.定义一个cell的标识为ID

     staticNSString*ID =@"mjcell";

  2.从缓存池中取出cell

     UITableViewCell*cell = [tableView  dequeueReusableCellWithIdentifier:ID];

3.如果缓存池中没有cell

     if(cell ==nil) {

        cell = [[UITableViewCellalloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];

    }

 4.设置cell的属性...

 return cell;

}

方法2:注册

[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]

拓展一:UITableView的cell侧滑删除按钮

//1.该行能不能编辑

-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPaht *)indexPath{

return YES;

}

//2.提交编辑

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{

//以下语句不能调换顺序,不然删除会崩溃报错

//1.删除对应数据源中的方法

[self.data removeObjectAtIndex:indexPath.row];

//2.删除界面上的哪一行

[tableView deleteRowsAtIndexPath:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

}

//3.设置删除按钮的文字(默认是英文的delete)

-(NSString *)tableView:(UITableView *)tableView  titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{

return @"删除";

}

拓展二:UITableView 的cell增加

先创建一个按钮,在按钮点击事件里设置进入编辑状态

[self.tableView setEditing:YES];

点击增加按钮,cell进入编辑状态,默认还是删除。想变成增加,需下面这个方法

//增加cell

-(UITableViewCellEditingStyle)tableview:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{

//默认情况下是删除

return UITableViewCellEditingStyleInsert;

}

这个时候,-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath这个方法就需要做出判断,如果是删除style执行删除cell,如果是增加style那就执行增加

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{

if(editingStyle == UITableViewCellEditingStyleDelete){

//以下语句不能调换顺序,不然删除会崩溃报错

//1.删除对应数据源中的方法

[self.data removeObjectAtIndex:indexPath.row];

//2.删除界面上的哪一行

[tableView deleteRowsAtIndexPath:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

}

}else if(editingStyle == UITableViewCellEditingStyleInsert){

//增加数据源

[self.data insertObject:@"新数据" atIndex:indexPath.row];

//刷新整个表格

//[self.tableView reloadData];(这里需要注意,如果想刷新tableview,用这个方法是没问题,但是这个是刷新整个表格,如果只是单纯增加或删除一行cell,没必要刷新整个表格,来耗内存)

[tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];

}

拓展三: UITableView 的cell移动

先创建一个按钮,在按钮点击事件里设置进入编辑状态

[self.tableView setEditing:YES];

进入编辑状态后,tableviewcell的右边会出现一个图标,进行拖拽到你想移动的cell位置

//移动cell

-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{

return YES;

}

-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{

//1.移除需要移动的cell

NSString *cellData = self.Data[sourceIndexPath.row];

//2.移除原始位置的数据

[self.data removeObjectAtIndex:sourceIndexPath.row];

//3.往目标位置插入一个数据

[self.data insertObject:cellData atIndex:destinationIndexPath.row];

(注意:如果没有以上这三点,只有两个移动cell函数的话,移动后的cell,在你滑动tableview的时候,数据还会变成原本数据,需要你对移动的数据进行重新处理)

}

最后,编辑完成,根据项目需求,在你点击完成的事件函数里,设置[self.tableView setEditing:NO];

为什么很多内置类如UITableViewController的delegate属性都是assign而不是retain呢?

会引起循环引用----若是retain,在alloc一次之后,若release一次,会导致内训泄漏,若release两次会导致两个 对象的dealloc嵌套执行,结果就是都没有执行成功,最后崩溃! 所有的引用计数系统,都存在循环应用的问题。例如下面的引用关系:

* 对象a创建并引用到了对象b. * 对象b创建并引用到了对象c. * 对象c创建并引用到了对象b.

这时候b和c的引用计数分别是2和1。 当a不再使用b,调用release释放对b的所有权,因为c还引用了b,所以b的引用计数为1,b不会被释放。 b不释放,c的引用计数就是1,c也不会被释放。从此,b和c永远留在内存中。 这种情况,必须打断循环引用,通过其他规则来维护引用关系。我们常见的delegate往往是assign方式的属性而不是 retain方式 的属性,赋值不会增加引用计数,就是为了防止delegation两端产生不必要的循环引用。 如果一个UITableViewController 对象a通过retain获取了UITableView对象b的所有权,这个UITableView对象b的 delegate又是a,如果这个delegate是retain方式的,那基本上就没有机会释放这两个对象了。自己在设计使用 delegate模式时,也要注意这点。

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

推荐阅读更多精彩内容