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