什么是UITableView
- 在眾多移動應用中,能看到各式各樣的列表數據
- 在iOS中,要實現展示列表數據,最常用的做法就是使用UITableView
- UITableView繼承自UIScrollView,因此支持垂直滾動,而且性能極佳
UITableView的兩種格式
-
UITableViewStylePlain
-
UISTableViewStyleGrouped
如何創建UITableView
-
來點簡單粗暴的,直接在Xcode里面的storyboar里面拖出來,也可以根據需求拉個UITableViewController
- 通過代碼
UITableView *myTableView = [UITableView alloc] init];
如何展示數據
- UITableView需要一個數據源(dataSource)方法來顯示數據
- UITableView會向dataSource查詢一共有幾組幾行以及每一行顯示什么數據
- 沒有設置數據源的UITableView都只是空殼子
- 凡是遵守UITableViewDataSource的OC對象,都可以是UITableView的數據源
tableView展示數據的過程
// 多少組數據
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
// 每一組有多少行數據
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
// 每一行顯示什么內容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
- tableView的常用設置
// 設置每一行cell的高度
self.tableView.rowHeight = 100;
// 設置每一組頭部的高度
self.tableView.sectionHeaderHeight = 50;
// 設置每一組尾部的高度
self.tableView.sectionFooterHeight = 50;
// 設置分割線顏色
self.tableView.separatorColor = [UIColor redColor];
// 設置分割線樣式
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
// 設置表頭控件
self.tableView.tableHeaderView = [[UISwitch alloc] init];
// 設置表尾控件
self.tableView.tableFooterView = [UIButton buttonWithType:UIButtonTypeContactAdd];
// 設置右邊索引文字的顏色
self.tableView.sectionIndexColor = [UIColor redColor];
// 設置右邊索引文字的背景色
self.tableView.sectionIndexBackgroundColor = [UIColor blackColor];
cell的簡介
- UITableView的每一行都是一個UITableViewCell
- UITableViewCell內部有個默認的子視圖:contentView,contentView是UITableViewCell所顯示內容的父視圖,可以顯示一些輔助指示視圖,通過UITableViewCell的accessoryType來顯示:
typedef NS_ENUM(NSInteger, UITableViewCellAccessoryType) {
UITableViewCellAccessoryNone, // don't show any accessory view
UITableViewCellAccessoryDisclosureIndicator, // regular chevron. doesn't track
UITableViewCellAccessoryDetailDisclosureButton __TVOS_PROHIBITED, // info button w/ chevron. tracks
UITableViewCellAccessoryCheckmark, // checkmark. doesn't track
UITableViewCellAccessoryDetailButton NS_ENUM_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED // info button. tracks
};
- contentView下默認有3個子視圖
- 其中2個是UILabel(通過UITableViewCell的textLabel屬性和detailLabel屬性訪問)
- 第3個是UIImageView(UITableViewcell.imageView);
- UITableViewCell還有一個UITableViewCellStyle屬性,用于決定使用ContentView的哪些子視圖,以及子視圖在ContentView中的位置
-
如下:
cell的重用原理
iOS設備的內存很有限,如果用UITableView展示成千上萬條數據就得創建成千上萬個UITableView對象的話,那將會耗盡iOS設備的內存.要解決這個問題,需要重用UITableView對象
-
重用原理:
當滾動列表時,部分UITableViewCell會移出窗口,UITableView會將窗口外的UITableViewCell放到一個對象池里,等待重用.當UITableView要求dataSource返回UITableViewCell時,dataSource會查看這個對象池,如果池中有未使用的UITableViewCell,dataSource會用新的數據配置這個UITableViewCell,然后返回給UITableView,重新顯示到窗口中,從而避免重復創建對象.
有一個灰常嚴重的問題:
有時候我們自定義一個UITableViewCell,每一行用的不一定是同一種的UITableViewCell,所以一個UITableView可以擁有不同種類的UITableViewCell,對象池中也會有很多不同類型的UITableViewCell,那么UITableView在重用UITableViewCell時可能會得到錯誤類型的UITableViewCell
有一個很NB的解決方法(其實也不是很牛逼.入門了的人都會知道><)
UITableViewCell有一個NSString *reuseIdentifier屬性,可以在初始化UITableViewCell的時候傳入一個特定的字符串標示來設置reuseIdentifier(一般用UITableViewCell的類名).當UITableView要求dataSource返回UITableViewCell時,先通過一個字符串標識到對象池中查找對應類型的UITableViewCell,如果有,就重用.如果沒有,就傳入這個字符串標識來初始化一個UITableViewCell對象
感覺用天朝的語言來描述好繞..直接寫個代碼好乏
傳統寫法
/**
* 每當有一個cell要進入視野范圍內,就會調用一次
*/
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// cell的標識
static NSString *ID = @"wine";
// 先去緩存池中查找可循環利用的cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 如果緩存池中沒有可循環利用的cell
if (!cell) {
// 自己創建一個cell
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID]
// 設置cell的屬性
...
return cell;
}
- 新寫法 (注冊cell)
- (void)viewDidLoad {
[super viewDidLoad];
// 注冊某個重用標識 對應的 Cell類型
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ID];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.先去緩存池中查找可循環利用的cell,
// 如果沒有的話,[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ID]方法會我們創建
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 2.設置數據
....
return cell;
}