掌握
設置UITableView的dataSource、delegate
UITableView多組數據和單組數據的展示
UITableViewCell的常見屬性
UITableView的性能優化(cell的循環利用)
自定義Cell
什么是UITableView?
能看到各式各樣的表格數據就是UITableView
如何展示數據
UITableView需要一個數據源(dataSource)來顯示數據
注意:但是如果刪掉原先控制器自動配置的View,用自己定義的UITableView,系統是默認遵守數據源和協議,不用設置!
UITableView會向數據源查詢一共有多少行數據以及每一行顯示什么數據等
沒有設置數據源的UITableView只是個空殼
凡是遵守UITableViewDataSource協議的OC對象,都可以是UITableView的數據源
/**
* dataSource是UITableViewDataSource類型,主要為UITableView提供顯示用的數據(UITableViewCell),指定UITableViewCell支持的編輯操作類型(insert,delete和reordering),并根據用戶的操作進行相應的數據更新操作,如果數據沒有更具操作進行正確的更新,可能會導致顯示異常,甚至crush。
delegate是UITableViewDelegate類型,主要提供一些可選的方法,用來控制tableView的選擇、指定section的頭和尾的顯示以及協助完成cell的刪除和排序等功能。
提到UITableView,就必須的說一說NSIndexPath。UITableView聲明了一個NSIndexPath的類別,主要用來標識當前cell的在tableView中的位置,該類別有section和row兩個屬性,前者標識當前cell處于第幾個section中,后者代表在該section中的第幾行。
UITableView只能有一列數據(cell),且只支持縱向滑動,當創建好的tablView第一次顯示的時候,我們需要調用其reloadData方法,強制刷新一次,從而使tableView的數據更新到最新狀態。
*/
tableView展示數據的過程
調用數據源的下面方法得知一共有多少組數據
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
調用數據源的下面方法得知每一組有多少行數據
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
調用數據源的下面方法得知每一行顯示什么內容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
初始MVC
MVC是一種設計思想,貫穿于整個iOS開發中,需要積累一定的項目經驗,才能深刻體會其中的含義和好處
MVC中的三個角色
M:Model,模型數據
V:View,視圖(界面)
C:Control,控制中心
注意:首先控制器會加載這個數據,然后根據這個數據的個數去創建對應的view
MVC的幾個明顯的特征和體現:
View上面顯示什么東西,取決于Model
只要Model數據改了,View的顯示狀態會跟著更改
Control負責初始化Model,并將Model傳遞給View去解析展示
Cell簡介以及屬性
UITableView的每一行都是一個UITableViewCell,通過dataSource的tableView:cellForRowAtIndexPath:(此方法就是UITableViewCell重用機制的一個初始化Cell的一個系統提供的一個方法)方法來初始化每一行
UITableViewCell內部有個默認的子視圖:contentView,contentView是UITableViewCell所顯示內容的父視圖,可顯示一些輔助指示視圖
accessoryType屬性:
輔助指示視圖的作用是顯示一個表示動作的圖標,可以通過設置UITableViewCell的accessoryType(其屬性)來顯示,默認是UITableViewCellAccessoryNone(不顯示輔助指示視圖),其他值如下:
屬性accessoryType就是設置指示器,也就是手機右邊的一個箭頭告訴用戶有的是可以點擊的,以下皆是其枚舉值
UITableViewCellAccessoryDisclosureIndicator
箭頭
UITableViewCellAccessoryDetailDisclosureButton按鈕 + 箭頭
UITableViewCellAccessoryCheckmark 對勾
UITableViewCellAccessoryNone 沒有
UITableViewCellAccessoryDetaiButton 嘆號按鈕
Cell的常見屬性
設置cell的背景顏色 backgroundColor優先級低于backgroundView
backgroundView使用方法:
創建一個View
UIView *bg = [[UIView alloc] init];
設置view的顏色,然后簡介的給cell賦值
bg.backgroundColor = [UIColor redColor];
再設置cell背景的顏色
cell.backgroundView= bg;
selectedBackgroundView使用方法:
創建一個View(也可以設置UIImageView作為cell的背景顏色)
UIView *selectedView= [[UIView alloc] init];
設置view的顏色,然后間接的賦值給cell
selectedView.backgroundColor = [UIColor redColor];
最后設置cell的背景顏色
cell.selectedBackgroundView= sele
還可以通過cell的accessoryView屬性來自定義輔助指示視圖(比如往右邊放一個開關)
注意:這里的cell的指的是通過UITableViewCell創建的一個對象的accessoryView屬性來自定義輔助的視圖
Cell.accessoryView= UITableViewCellAccessoryCheckmark;
cell.accessoryView = [UIbutton alloc]init];(可以在右邊自定義控件可以放一個按鈕或者一個開關)
注意:以上cell的屬性包含了4個屬性
Cell的重用原理
iOS設備的內存有限,如果用UITableView顯示成千上萬條數據,就需要成千上萬個UITableViewCell對象的話,那將會耗盡iOS設備的內存。要解決該問題,需要重用UITableViewCell對象
重用原理:當滾動列表時,部分UITableViewCell會移出窗口,UITableView會將窗口外的UITableViewCell放入一個對象池中,等待重用。當UITableView要求dataSource返回UITableViewCell時,dataSource會先查看這個對象池,如果池中有未使用的UITableViewCell,dataSource會用新的數據配置這個UITableViewCell,然后返回給UITableView,重新顯示到窗口中,從而避免創建新對象
還有一個非常重要的問題:有時候需要自定義UITableViewCell(用一個子類繼承UITableViewCell),而且每一行用的不一定是同一種UITableViewCell,所以一個UITableView可能擁有不同類型的UITableViewCell,對象池中也會有很多不同類型的UITableViewCell,那么UITableView在重用UITableViewCell時可能會得到錯誤類型的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
static NSString *ID = @"mjcell";
2.從緩存池中取出cell
UITableViewCell*cell = [tableView dequeueReusableCellWithIdentifier:ID];
3.如果緩存池中沒有cell
if (cell ==nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:ID];
}
4.設置cell的屬性...
return cell;
}
方法2:注冊
另一中性能優化的寫法:
0.先確定cell的重用標識
1.注冊帶重用標識的cell
2.從緩存池中取是否有帶重用標識的cell(如果沒有,系統會根據注冊自動創建一個相應的cell返回給我們)
3.覆蓋cell上面的數據
說明:當cell離開屏幕的時候,就會放到tableView的緩存池中,這時候緩存池才有數據
3.0 先確定cell的重用標識:命名規范:cell類型+ID
static NSString *ID = @"carID"; // static修飾局部變量,局部變量從執行后始終存在,
但不能被其它函數使用, 當再次進入該函數時, 將保存上次的結果。其它與局部變量一樣。
static BOOL isReged =NO;
3.1 先注冊帶ID的cell
if (isReged ==NO) {
warning registerCell需要注意的3點,面試可能會問到
該方法是伴隨著UICollectionView出現的,也就是iOS6出現的
采用注冊創建出來的cell,默認是Default樣式,所以一般注冊大部分都用在自定義cell的時候
需要注意的是 [tableView registerNib:<#(UINib *)#>
forCellReuseIdentifier:<#(NSString *)#>] 是iOS5出現的
編碼規范:xib自定義cell一般用注冊
[tableView
registerClass:[UITableViewCell class] forCellReuseIdentifier:ID];
isReged =YES;
}
3.2 查看緩存池中是否有帶重用標識的cell
緩存池方法中封裝了,如果緩存池中沒有,就根據注冊創建新的cell,然后返回給我們一個帶ID的cell
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:ID];
3.3 覆蓋cell上的數據
XMGCar *car = self.cars[indexPath.row];
cell.textLabel.text = [NSString...
3.4返回cell
return cell;
}
方法3:storyboard
另一中性能優化的寫法(storyboard):
0.先確定cell的重用標識
1.將storyboard中的tableView中的cell的重用標志賦值
2.從緩存池中取是否有帶重用標識的cell
(2.1
如果沒有,系統會根據注冊自動創建一個相應的cell返回給我們;
2.2 如果也沒有注冊過,系統會根據storyboard中寫好的帶重用標志的cell來自動創建,然后返回)
3.覆蓋cell上面的數據
說明:當cell離開屏幕的時候,就會放到tableView的緩存池中,這時候緩存池才有數據
3.返回每行內容:該方法,只有當cell顯示在屏幕上的時候才會調用,是一種懶加載的思想
warning 如果有注冊,就不會觸發storyboard的創建新cell的機制.只有沒有注冊過,并且storyboard中沒有標記相應cell 的時候,dequeueReusableCellWithIdentifier才會返回nil
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
3.0 先確定cell的重用標識:命名規范:數據的模型+ID
static NSString *ID
= @"carID"; static修飾局部變量,局部變量只會分配一次內存地址
3.1 查看緩存池中是否有帶重用標識的cell
緩存池方法中封裝了,如果緩存池中沒有,就根據注冊創建新的cell,然后返回給我們一個帶ID的cell
后面還封裝了一層,如果也沒有注冊呢,會根據storyboard中是否標記了在重用cell,來創建一個新的cell然后返回
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:ID];
3.3 覆蓋cell上的數據
XMGCar *car = self.cars[indexPath.row];
cell.textLabel.text = [N...
return
cell;
}
3.修改控件屬性(一半在cell的創建方法中設置initWithStyle)
cell.imageView.layer.cornerRadius= 22;
設置圓角為正方形邊長一半(內切圓半徑)
cell.imageView.layer.masksToBounds= YES; 設置將位于imageView之下的layer都遮蓋住(默認是NO) 等效代碼是:cell.imageView.clipsToBounds
設置字體以及文字顏色
cell.textLabel.textColor= [UIColor brownColor];
cell.detailTextLabel.font= [UIFont
systemFontOfSize:12.0];
cell.detailTextLabel.textColor= [UIColor grayColor];
設置輔助視圖
cell.accessoryType= UITableViewCellAccessoryDetailButton;
使用xib封裝一個view的步驟
新建一個xib文件描述一個view的內部結構(假設叫做MJTgCell.xib)
新建一個自定義的類
(自定義類需要繼承自系統自帶的view, 繼承自哪個類, 取決于xib根對象的Class)
新建類的類名最好跟xib的文件名保持一致(比如類名就叫做MJTgCell)
將xib中的控件 和 自定義類的.m文件 進行連線
提供一個類方法返回一個創建好的自定義view(屏蔽從xib加載的過程)
提供一個模型屬性讓外界傳遞模型數據
重寫模型屬性的setter方法,在這里將模型數據展示到對應的子控件上面
Delegate的使用場合
對象A內部發生了一些事情,想通知對象B
對象B想監聽對象A內部發生了什么事情
對象A想在自己的方法內部調用對象B的某個方法,并且對象A不能對對象B有耦合依賴
對象A想傳遞數據給對象B
……
以上情況,結果都一樣:對象B是對象A的代理(delegate)
使用delegate的步驟
先搞清楚誰是誰的代理(delegate)
定義代理協議,協議名稱的命名規范:控件類名+ Delegate
定義代理方法
代理方法一般都定義為@optional
代理方法名都以控件名開頭
代理方法至少有1個參數,將控件本身傳遞出去
設置代理(delegate)對象 (比如myView.delegate = xxxx;)
代理對象遵守協議
代理對象實現協議里面該實現的方法
在恰當的時刻調用代理對象(delegate)的代理方法,通知代理發生了什么事情
(在調用之前判斷代理是否實現了該代理方法)
通過代碼自定義cell(cell的高度不一致)
1.新建一個繼承自UITableViewCell的類
注意:一個是初始化方法一個設置子控件的方法一個是設置數據的對象的set方法
2.重寫initWithStyle:reuseIdentifier:方法
添加所有需要顯示的子控件(不需要設置子控件的數據和frame, 子控件要添加到contentView中
進行子控件一次性的屬性設置(有些屬性只需要設置一次, 比如字體\固定的圖片等等但是設置frame不行)
3.提供2個模型
數據模型: 存放文字數據\圖片數據
(字典轉模)
frame模型: 存放數據模型\所有子控件的frame\cell的高度
4.cell擁有一個frame模型(不要直接擁有數據模型)
5.重寫frame模型屬性的setter方法: 在這個方法中設置子控件的顯示數據和frame
6.frame模型數據的初始化已經采取懶加載的方式(每一個cell對應的frame模型數據只加載一次)
UITextField
通過UITextField的代理方法能夠監聽鍵盤最右下角按鈕的點擊
成為UITextField的代理
self.textField.delegate = self;
遵守UITextFieldDelegate協議,實現代理方法
(BOOL)textFieldShouldReturn:(UITextField *)textField;
在UITextField左邊放一個view
self.textField.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 8, 0)];
self.textField.leftViewMode = UITextFieldViewModeAlways;
***************************筆記************************
tableView常見屬性
修改cell的高度,也就是行高
self.tableView.rowHeight= 60;
修改組頭.組尾的高度(Plain樣式下生效): 在Group樣式下,組頭組尾高度都是系統默認的
self.tableView.sectionHeaderHeight= 2;
self.tableView.sectionFooterHeight= 222;
設置tableView的表頭表尾視圖
一般用于做下拉刷新,banner
self.tableView.tableHeaderView= [UIButton
buttonWithType:UIButtonTypeContactAdd];
self.tableView.tableFooterView= [[UISwitch alloc] init];
設置分割線顏色:
[UIColor clearColor]如果設置成透明色就表示分割線取消顯示
warning 在tableView上,盡量避免使用透明色
self.tableView.separatorColor= [UIColor orangeColor];
UITableViewCellSeparatorStyleNone 取消分割線的顯示
warning
UITableViewCellSeparatorStyleNone->UITableViewCellSelectionStyleNone
self.tableView.separatorStyle= UITableViewCellSeparatorStyleNone;
隱藏狀態欄
- (BOOL)prefersStatusBarHidden
{
return YES;
}
設置cell的屬性
設置cell的背景顏色 backgroundColor優先級低于backgroundView
cell.backgroundColor= [UIColor colorWithRed:arc4random_uniform(255)/255.0 green:arc4random_uniform(255)/255.0 blue:arc4random_uniform(255)/255.0 alpha:1];
UIView*bg = [[UIView alloc] init];
bg.backgroundColor= [UIColor grayColor];
cell.backgroundView
= bg; 一般用于UIIMageView展示公司logo
typedef NS_ENUM(NSInteger,
UITableViewCellAccessoryType)
{
UITableViewCellAccessoryNone,
don't show any
accessory view 默認沒有
UITableViewCellAccessoryDisclosureIndicator, regular chevron. doesn't track 尖尖
UITableViewCellAccessoryDetailDisclosureButton, info button w/ chevron. tracks 圈! + 尖尖
UITableViewCellAccessoryCheckmark,
checkmark. doesn't track 對號
UITableViewCellAccessoryDetailButton NS_ENUM_AVAILABLE_IOS(7_0) // info button. tracks 圈!
設置輔助視圖
accessoryView優先級高
NSUIntegerrow = arc4random_uniform(255);
if (row % 2) {
cell.accessoryView = [[UISwitch alloc] init];
}else
{
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}
tableView如何展示數據?
mutiSectionsTableView
tableView如何展示數據?
- 通過數據源
@property (nonatomic,
assign) id
<UITableViewDataSource> dataSource;
- 設置數據源
1.在viewDidLoad方法中設置
tableView.dataSource =
self;
2.在storyboard中拖線
遵守數據源協議<UITableViewDataSource>
實現數據源方法
多少組數據
(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
每一組有多少行數據
(NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section;
每一行顯示什么內容(note:必須是UITableViewCell或者其子類)
- (UITableViewCell
*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath;
indexPaht.section 第幾組
indexPath.row 第幾行
每一組的頭部section 代表行數
- (NSString
*)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section;
每一組的尾部
- (NSString
*)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
為什么要數據獨立?
新需求再添加一組數據時候,需要修改全部數據源方法!
思路:將所有需要修改的數據集中到一處
- 創建一個新的數組屬性
@property (nonatomic, strong) NSArray groups; /*< group模型數組 */
- 通過懶加載為數組賦值
懶加載
- (NSArray *)groups
{
if (!_groups) {
XMGGroup *g0 = [[XMGGroup alloc] init];
g0.header = @"adc";
g0.footer = @"物理輸出脆皮";
g0.heros = @[[XMGHero heroWithName:@"艾希" Icon:@"hanbing"],
[XMGHero
heroWithName:@"崔斯特娜" Icon:@"xiaopao"],
[XMGHero
heroWithName:@"金克斯" Icon:@"金克斯"]];
XMGGroup *g1 = [[XMGGroup alloc] init];
g1.header = @"apc";
g1.footer = @"法術輸出脆皮";
g1.heros = @[[XMGHero heroWithName:@"阿貍" Icon:@"ali"],
[XMGHero
heroWithName:@"火男" Icon:@"huonan"],
[XMGHero
heroWithName:@"球女" Icon:@"qiunv"]];
XMGGroup *g2 = [[XMGGroup alloc] init];
g2.header = @"上單";
g2.footer = @"上單爸爸不好惹";
g2.heros = @[[XMGHero heroWithName:@"大保健" Icon:@"dabaojian"],
];
_groups = @[g0, g1, g2];
}
return _groups;
}
這樣再添加數據,只需要對懶加載中的數據進行操作即可
實際開發中,所用的數據也是從服務器拿到后展示
分析模型的創建
組頭
組尾
cell上的內容(數組)
每個cell上的內容分為name和icon
創建hero模型
單組數據展示
- 數據源方法:返回多少組可以不實現
- cell上自帶3個展示信息的子控件
cell.textLabel.text =
car.name;
系統自帶的cell的非value2樣式并且有數據才展示
cell.imageView.image =
[UIImage imageNamed:car.icon];
系統自帶cell的非default樣式并且有數據時候才展示
cell.detailTextLabel.text
= car.money;
- 復習簡單plist文件解析
1.拿到plist的文件路徑
NSString *filePath = [[NSBundle mainBundle]
pathForResource:@"cars.plist"ofType:nil];
2.創建對應的JSON數據
NSArray *dicts =
[NSArray arrayWithContentsOfFile:filePath];
3.JSON->Model
NSMutableArray
*arrayM = [NSMutableArray arrayWithCapacity:dicts.count];
for (NSDictionary *dict in
dicts) {
3.1 Dict->Model
XMGCar
*obj = [XMGCar carWithDict:dict];
[arrayM
addObject:obj];
}
- Dict->Model
- (instancetype)carWithDict:(NSDictionary *)dict
{
XMGCar
*car = [[self alloc] init];
car.name = dict[@"name"];
car.icon = dict[@"icon"];
car.money = dict[@"money"];
kvc 相當于上面3行
[car
setValuesForKeysWithDictionary:dict];
return car;
}
pragma mark - cell常見屬性
方法抽取的技巧就是將變量寫成參數傳進來
相同業務邏輯的的代碼盡量抽取成方法
- (void)setupCellProperty:(UITableViewCell *)cell
row:(NSInteger)row
{
cell的常見屬性
設置cell的背景顏色
cell.backgroundColor = (row % 2)? [UIColor yellowColor]: [UIColor orangeColor];
設置cell的背景視圖,并且backgroundView的優先級比backgroundColor高一些
UIView *cellBg = [[UIView alloc] init];
cellBg.backgroundColor = [UIColor grayColor];
cell.backgroundView = cellBg;
/*
UITableViewCellAccessoryNone,
// don't show any accessory view
UITableViewCellAccessoryDisclosureIndicator,
// 尖尖regular chevron. doesn't track
UITableViewCellAccessoryDetailDisclosureButton, // 圈i
- 尖尖info button w/ chevron. tracks
UITableViewCellAccessoryCheckmark,
// 小對勾checkmark. doesn't track
UITableViewCellAccessoryDetailButton
NS_ENUM_AVAILABLE_IOS(7_0) // 圈i info button. tracks
*/
cell的輔助視圖樣式
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell的輔助視圖,作用優先級高于accessoryType
cell.accessoryView = [[UISwitch alloc] init];
/*
UITableViewCellSelectionStyleNone, // 設置沒有選中樣式
UITableViewCellSelectionStyleBlue, // 在iOS6之前,選中背景色變藍,iOS7之后,和gray相同
UITableViewCellSelectionStyleGray, // 默認樣式
UITableViewCellSelectionStyleDefault
NS_ENUM_AVAILABLE_IOS(7_0) // 默認樣式
*/
cell.selectionStyle = UITableViewCellSelectionStyleGray;
在UITableViewCellSelectionStyleNone樣式中,設置selectedBackgroundView是無效的
/*
在
UITableViewCellSelectionStyleBlue, // 在iOS6之前,選中背景色變藍,iOS7之后,和gray相同
UITableViewCellSelectionStyleGray, // 默認樣式
UITableViewCellSelectionStyleDefault
NS_ENUM_AVAILABLE_IOS(7_0) // 默認樣式
3種樣式下,selectedBackgroundView他的優先級高于selectionStyle
*/
UIView
*cellsBg = [[UIView alloc] init];
cellsBg.backgroundColor = [UIColor redColor];
cell.selectedBackgroundView = cellsBg;
/*
contentView = 0x7f96fb553470:
cell.textLabel.superview = 0x7f96fb553470
==0x7f96fb553470
==0x7f96fb553470
*/
cell上面的子控件不是直接添加在cell上,而是添加到contentView上
NSLog(@"contentView = %p: cell.textLabel.superview =
%p==%p==%p", cell.contentView, cell.textLabel.superview,
cell.imageView.superview, cell.detailTextLabel.superview);
}
- 注意:cell上面的子控件要添加到cell.contentView上
常見代理/易錯屬性
- 前兩者易錯
選中某一行時候調用
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"%s, row = %ld",__FUNCTION__, indexPath.row);
}
取消選中某一行時候調用
- (void)tableView:(UITableView *)tableView
didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"%s, row = %ld",__FUNCTION__, indexPath.row);
}
根據indexPath返回對應的高度
(CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
return 222;
}
return 88;
}
- 分割線樣式的枚舉容易寫錯
warning 在設置分割線樣式為None的時候如果無效,先看你是否搞混了下列2個枚舉
/*
UITableViewCellSeparatorStyleNone
UITableViewCellSelectionStyleNone
*/
self.tableView.separatorStyle =
UITableViewCellSeparatorStyleNone;
cellWithTableView:
cell獲取封裝
- 將獲取cell的代碼全部copy到cell內部,發現需要用到變量tableView,傳入即可
- 傳統封裝
- (instancetype)cellWithTableView:(UITableView
*)tableView
{
1.確定重用標識
static NSString *ID = nil;
if (ID == nil)
{
ID = [NSString stringWithFormat:@"%@ID",
NSStringFromClass(self)];
}
2.從緩存池中取
XMGCarCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
3.如果緩存池中沒有,就自己創建
if (!cell) {
cell = [[XMGCarCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:ID];
}
return cell;
}
- 注冊封裝
- (instancetype)cellWithTableView:(UITableView
*)tableView
{
確定重用標示(規范的寫法)
static NSString *ID = nil;
if (ID == nil)
{
ID = [NSString stringWithFormat:@"%@ID",
NSStringFromClass(self)];
}
如果沒有注冊過,就注冊1次
static BOOL isReged = NO;
if (isReged == NO)
{
[tableView registerClass:self
forCellReuseIdentifier:ID];
isReged = YES;
NSLog(@"%s, line = %d",FUNCTION,LINE);
}
1.緩存池
這里應該是XMGCarCell *cell,寫成id 的原因是為了拖個代碼塊
id cell = [tableView
dequeueReusableCellWithIdentifier:ID];
return cell;
}
數據覆蓋封裝
- 為cell添加模型屬性
@property (nonatomic, strong) XMGCar car; /*< carModel */
- 重寫模型set方法完成內部賦值
- (void)setCar:(XMGCar *)car
{
_car =
car;
self.imageView.image = car.icon;
self.textLabel.text = car.name;
}
封裝后創建cell的數據源方法只需要3步
獲取cell
覆蓋數據
返回cell
-
(UITableViewCell
*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath {3.1 獲取cell
XMGCarCell *cell = [XMGCarCell cellWithTableView:tableView];
3.2 數據覆蓋
這樣寫的好處就是,將cell覆蓋數據一行完成,具體覆蓋了哪些數據,進入cell內部看
XMGGroup
*g = self.groups[indexPath.section];
XMGCar
*car = g.cars[indexPath.row];
cell.car
= car;
3.3.返回cell
return cell;
}