# 一.目录
# 二. 解析
### 1. - UITableView的基本使用方式
**1.1UITableView:整体上来说,就是一个表格控件,在ios的实际开发过程中, UITableView的使用相当广泛,是非常重要的一个控件,所以一定要引起重视,特别是对于新手来说;**
**1.2. UITableView就是表格控件**
- UITableView由行和列来组成
- UITableView中每行只有1列
- 每行中保存的都是一个UITableViewCell对象
**1.3. UITableView一般用来展示表格数据、可以滚动(继承自UIScrollView)、性能极佳**
如果没有UITableView, 实现类似的功能只能自己通过循环创建控件, 性能差
### 2. - UITableView的两种显示方式
1 // this protocol represents the data model object. as such, it supplies no information about appearance (including the cells) 2 3 @protocol UITableViewDataSource<NSObject> 4 5 @required 6 7 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; 8 9 // Row display. Implementers should *always* try to reuse cells by setting each cell‘s reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier: 10 // Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls) 11 12 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; 13 14 @optional 15 16 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; // Default is 1 if not implemented
// 返回对应组有多少行 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; // 根据索引,返回每组每行的单元格cell到底长什么样 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
而对于,返回组的数量的数据源方法来说,是可选实现的方法, 默认不实现的情况下,表示组数为1;如果有多个组,就必须要有这个方法:
// 返回有多少组 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
1 - (void)viewDidLoad { 2 [super viewDidLoad]; 3 //设置控制器为数据源对象 4 self.tableView.dataSource = self; 5 }
然后让当前控制器遵守数据源协议:
@interface ViewController ()<UITableViewDataSource>
1 - (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; // fixed font style. use custom view (UILabel) if you want something different //组标题 2 - (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section; //组描述
1 - (void)viewDidLoad { 2 [super viewDidLoad]; 3 //设置控制器为数据源对象 4 self.tableView.dataSource = self; 5 //设置统一的行高 6 self.tableView.rowHeight = 70; 7 }
预设行高: 主要用于动态计算cell行高的情况下
1 - (void)viewDidLoad { 2 [super viewDidLoad]; 3 //设置控制器为数据源对象 4 self.tableView.dataSource = self; 5 6 //预设行高 7 self.tableView.estimatedRowHeight = 300; 8 }
基本属性解读:
右侧属性栏中属性分为三大类属性:1、Table View 2、Scroll View 3、 View
下面只看Table View中的属性:
Content: Dynamic Prototypes 动态单元格
Static Cells 静态单元格
Prototype: Cells cell的行数
Style 样式 : Plain 简单样式(未分组)
Grouped 分组样式
separator : 分隔线属性
selection : 单前选中行
background : 背景色
1 NS_CLASS_AVAILABLE_IOS(2_0) @interface UITableView : UIScrollView <NSCoding> 2 3 - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style NS_DESIGNATED_INITIALIZER; // must specify style at creation. -initWithFrame: calls this with UITableViewStylePlain 4 - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; 5 6 @property (nonatomic, readonly) UITableViewStyle style; 7 @property (nonatomic, weak, nullable) id <UITableViewDataSource> dataSource; 8 @property (nonatomic, weak, nullable) id <UITableViewDelegate> delegate; 9 @property (nonatomic) CGFloat rowHeight; // will return the default value if unset 10 @property (nonatomic) CGFloat sectionHeaderHeight; // will return the default value if unset 11 @property (nonatomic) CGFloat sectionFooterHeight; // will return the default value if unset 12 @property (nonatomic) CGFloat estimatedRowHeight NS_AVAILABLE_IOS(7_0); // default is 0, which means there is no estimate 13 @property (nonatomic) CGFloat estimatedSectionHeaderHeight NS_AVAILABLE_IOS(7_0); // default is 0, which means there is no estimate 14 @property (nonatomic) CGFloat estimatedSectionFooterHeight NS_AVAILABLE_IOS(7_0); // default is 0, which means there is no estimate 15 @property (nonatomic) UIEdgeInsets separatorInset NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR; // allows customization of the frame of cell separators 16 17 @property (nonatomic, strong, nullable) UIView *backgroundView NS_AVAILABLE_IOS(3_2); // the background view will be automatically resized to track the size of the table view. this will be placed as a subview of the table view behind all cells and headers/footers. default may be non-nil for some devices.
源文件前半部分代码如上,我们可以看到,越靠前的属性越为重要:
第6行 UITableViewStyle 枚举类型的 style 属性,是用于设置UITableView的style样式,源文件中枚举类型如下:
1 typedef NS_ENUM(NSInteger, UITableViewStyle) { 2 UITableViewStylePlain, // regular table view 3 UITableViewStyleGrouped // preferences style table view 4 };
通过查看底层,我们可以看出,越是靠前的属性,就越是重要,
可以看出tableView的样式和工具栏上的一样是两种,Plain和Grouped。
第7行是提供了一个设置数据源方法的属性 上面已经有介绍了
第8行提供了一个tableView代理方法的属性
第9行为row的高度,也就是行高
第10行为头View高度 ---组标题
第11行为尾部View高度 ---组描述
1 //设置每行之间分割线的颜色和样式 2 self.tableView.separatorColor = [UIColor redColor]; 3 self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
1 //设置tableview的header 2 UIView *hearderVw = [[UIView alloc]init]; 3 hearderVw.backgroundColor = [UIColor redColor]; 4 hearderVw.alpha = 0.5; 5 //当一个控件要作为tableview的header view来显示的时候,此时设置的x,y,w都无效,只有高h有效 6 hearderVw.frame = CGRectMake(0, 0, 0, 150); 7 self.tableView.tableHeaderView = hearderVw; 8 9 //设置tableview的footer view 10 UIView *footerVw = [[UIView alloc]init]; 11 footerVw.backgroundColor = [UIColor blueColor]; 12 //当一个控件要作为tableview的footer view来显示的时候,此时设置的y,w都无效,只有高h和x有效 13 footerVw.frame = CGRectMake(10, 0, 0, 200); 14 self.tableView.tableFooterView = footerVw;
1 NS_CLASS_AVAILABLE_IOS(2_0) @interface UITableViewCell : UIView <NSCoding, UIGestureRecognizerDelegate> 2 3 // Designated initializer. If the cell can be reused, you must pass in a reuse identifier. You should use the same reuse identifier for all cells of the same form. 4 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(nullable NSString *)reuseIdentifier NS_AVAILABLE_IOS(3_0) NS_DESIGNATED_INITIALIZER; 5 - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; 6 7 // Content. These properties provide direct access to the internal label and image views used by the table view cell. These should be used instead of the content properties below. 8 @property (nonatomic, readonly, strong, nullable) UIImageView *imageView NS_AVAILABLE_IOS(3_0); // default is nil. image view will be created if necessary. 9 10 @property (nonatomic, readonly, strong, nullable) UILabel *textLabel NS_AVAILABLE_IOS(3_0); // default is nil. label will be created if necessary. 11 @property (nonatomic, readonly, strong, nullable) UILabel *detailTextLabel NS_AVAILABLE_IOS(3_0); // default is nil. label will be created if necessary (and the current style supports a detail label). 12 13 // If you want to customize cells by simply adding additional views, you should add them to the content view so they will be positioned appropriately as the cell transitions into and out of editing mode. 14 @property (nonatomic, readonly, strong) UIView *contentView; 15 16 // Default is nil for cells in UITableViewStylePlain, and non-nil for UITableViewStyleGrouped. The ‘backgroundView‘ will be added as a subview behind all other views. 17 @property (nonatomic, strong, nullable) UIView *backgroundView;
* 性能优化步骤:
1 @implementation ViewController
2 static NSString *ID = @"cell_id”; 3 //这里要申明一下ID,也就是缓存池创建的cell的标记符 在ViewController里面申明这个ID是什么! 4 5 //添加static 关键字, 这样创建的ID会转移保存到静态区,这样每次创建的ID和 常量”cell_id” 都不会被销毁, 下一次创建的时候 直接调用,不会重复创建了; 6 //2.创建一个单元格 有三种方式:如下 推荐使用第三种; 7 // 2.1> 先从缓存池中尝试去取一个单元格 8 // 用来标识缓存池中的cell的id (可重用id) 9 // static NSString *ID = @"cell_id"; 10 // 根据可重用ID, 在缓存池中查找对应的cell 11 12 //方式1 :原始方式 方式1是每移除一个,就创建一个cell,会不停的创建,性能低,总有内存爆满的时候,会崩溃 13 UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:nil]; 14 15 //方式2: 如刚好一个 页面有8个cell,一启动会创建8个,当滚动一点点的时候,第一个没有进缓存池,而第9个已经出来了,这个时候又多了一个cell,这种方式至少会创建9个,如果是ABAB型的,还会有第10个,也有点不妥, 16 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; 17 if (cell == nil) { 18 cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; 19 } 20 //方式3:这种方式是最好的,如,也是ABAB类型的,到缓存池里面找和创建cell是一步搞定,底层是直接就写好了的, 但注意,这里需要在启动程序的时候注册一个cell,也就是在viewDidLoad里面, 推荐用这种!! 21 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID forIndexPath:indexPath]; 22 //此时,当一个cell从屏幕滚出去以后,不会销毁,而是放到了"缓存池"中;
23 #pragma mark ----viewDidLoad 设置数据源对象 24 - (void)viewDidLoad { 25 [super viewDidLoad]; 26 //设置控制器为数据源对象 27 self.tableView.dataSource = self; 28 //设置统一的行高 29 self.tableView.rowHeight = 70; 30 31 //注册一个cell 32 [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ID]; 33 } 34 ——> 35 这个是为方法3注册的一个cell,便于方式3调用; 要用这种方法,必须要先注册一个cell 在viewDidload 里面注册,注册就是告诉系统,我们用的ID到底是什么类型的cell,
// Called after the user changes the selection.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
@protocol UIAlertViewDelegate <NSObject>
@optional
// Called when a button is clicked. The view will be automatically dismissed after this call returns
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex NS_DEPRECATED_IOS(2_0, 9_0);
1 ====>> 代码实现: 2 DXTableViewCell.h 3 #import <UIKit/UIKit.h> 4 @interface DXTableViewCell : UITableViewCell 5 @end 6 7 // HMTableViewCell.m 8 #import "HMTableViewCell.h" 9 @implementation HMTableViewCell 10 11 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 12 return [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier]; 13 } 14 @end 15 16 这里重定义的类是为了,来刷新数据的时候,让cell始终处于一种状态:UITableViewCellStyleSubtitle,这样定义之后,物理注册的时候cell是什么状态,最后都会返回这个状态; 17 18 didSelectRowAtIndexPath 选中某行做什么事情, 很重要!!! 里面可以写任何操作方式 19 -------------------------------------------------- 20 @interface ViewController () <UITableViewDataSource, UITableViewDelegate, UIAlertViewDelegate> //同时让控制器要继承UIAlertViewDelegate这个协议 21 // 记录当前选中行 这里需要先定义一个属性,让下面的代理方法的索引选中的行,赋值给它,便于局部刷新的时候可以调用 22 @property (nonatomic, strong) NSIndexPath *idxPath; 23 -------------------------------------------------- 24 #pragma mark - table view的代理方法 25 // 当用户选中某个的时候会触发这个事件(会执行这个方法) 26 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 27 28 self.idxPath = indexPath; //把当前选中的行赋值给这个属性 29 30 // 立刻取消某行的选中效果(取消选中) 31 [tableView deselectRowAtIndexPath:indexPath animated:YES]; 32 33 // 0. 获取当前选中行的模型数据 34 HMHero *hero = self.heros[indexPath.row]; 35 36 // 1. 弹出一个UIAlertView 37 UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"编辑" message:nil delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil]; 38 39 // 1.1修改alert view的样式, 让alertView中有一个文本框 40 alertView.alertViewStyle = UIAlertViewStylePlainTextInput; 41 42 // 1.2获取alert view中的文本框 43 UITextField *txtField = [alertView textFieldAtIndex:0]; 44 45 // 1.3把英雄的名字设置到文本框中 46 txtField.text = hero.name; 47 48 //2.显示出来 49 [alertView show]; 50 }
原文:http://www.cnblogs.com/anRanTimes/p/5115043.html