基礎(chǔ) (十五) : UITableView

掌握

設(shè)置UITableView的dataSource、delegate

UITableView多組數(shù)據(jù)和單組數(shù)據(jù)的展示

UITableViewCell的常見屬性

UITableView的性能優(yōu)化(cell的循環(huán)利用)

自定義Cell

什么是UITableView?

能看到各式各樣的表格數(shù)據(jù)就是UITableView

1.png
2.png

如何展示數(shù)據(jù)

UITableView需要一個(gè)數(shù)據(jù)源(dataSource)來顯示數(shù)據(jù)

注意:但是如果刪掉原先控制器自動(dòng)配置的View,用自己定義的UITableView,系統(tǒng)是默認(rèn)遵守?cái)?shù)據(jù)源和協(xié)議,不用設(shè)置!

UITableView會(huì)向數(shù)據(jù)源查詢一共有多少行數(shù)據(jù)以及每一行顯示什么數(shù)據(jù)等

沒有設(shè)置數(shù)據(jù)源的UITableView只是個(gè)空殼

凡是遵守UITableViewDataSource協(xié)議的OC對(duì)象,都可以是UITableView的數(shù)據(jù)源

/**

 *  dataSource是UITableViewDataSource類型,主要為UITableView提供顯示用的數(shù)據(jù)(UITableViewCell),指定UITableViewCell支持的編輯操作類型(insert,delete和reordering),并根據(jù)用戶的操作進(jìn)行相應(yīng)的數(shù)據(jù)更新操作,如果數(shù)據(jù)沒有更具操作進(jìn)行正確的更新,可能會(huì)導(dǎo)致顯示異常,甚至crush。




 delegate是UITableViewDelegate類型,主要提供一些可選的方法,用來控制tableView的選擇、指定section的頭和尾的顯示以及協(xié)助完成cell的刪除和排序等功能。




 提到UITableView,就必須的說一說NSIndexPath。UITableView聲明了一個(gè)NSIndexPath的類別,主要用來標(biāo)識(shí)當(dāng)前cell的在tableView中的位置,該類別有section和row兩個(gè)屬性,前者標(biāo)識(shí)當(dāng)前cell處于第幾個(gè)section中,后者代表在該section中的第幾行。




 UITableView只能有一列數(shù)據(jù)(cell),且只支持縱向滑動(dòng),當(dāng)創(chuàng)建好的tablView第一次顯示的時(shí)候,我們需要調(diào)用其reloadData方法,強(qiáng)制刷新一次,從而使tableView的數(shù)據(jù)更新到最新狀態(tài)。

*/


3.png

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;
4.png

初始MVC

MVC是一種設(shè)計(jì)思想,貫穿于整個(gè)iOS開發(fā)中,需要積累一定的項(xiàng)目經(jīng)驗(yàn),才能深刻體會(huì)其中的含義和好處

MVC中的三個(gè)角色

M:Model,模型數(shù)據(jù)

V:View,視圖(界面)

C:Control,控制中心

注意:首先控制器會(huì)加載這個(gè)數(shù)據(jù),然后根據(jù)這個(gè)數(shù)據(jù)的個(gè)數(shù)去創(chuàng)建對(duì)應(yīng)的view

MVC的幾個(gè)明顯的特征和體現(xiàn):

View上面顯示什么東西,取決于Model

只要Model數(shù)據(jù)改了,View的顯示狀態(tài)會(huì)跟著更改

Control負(fù)責(zé)初始化Model,并將Model傳遞給View去解析展示

Cell簡介以及屬性

UITableView的每一行都是一個(gè)UITableViewCell,通過dataSource的tableView:cellForRowAtIndexPath:(此方法就是UITableViewCell重用機(jī)制的一個(gè)初始化Cell的一個(gè)系統(tǒng)提供的一個(gè)方法)方法來初始化每一行

UITableViewCell內(nèi)部有個(gè)默認(rèn)的子視圖:contentView,contentView是UITableViewCell所顯示內(nèi)容的父視圖,可顯示一些輔助指示視圖

accessoryType屬性:

輔助指示視圖的作用是顯示一個(gè)表示動(dòng)作的圖標(biāo),可以通過設(shè)置UITableViewCell的accessoryType(其屬性)來顯示,默認(rèn)是UITableViewCellAccessoryNone(不顯示輔助指示視圖),其他值如下:

屬性accessoryType就是設(shè)置指示器,也就是手機(jī)右邊的一個(gè)箭頭告訴用戶有的是可以點(diǎn)擊的,以下皆是其枚舉值

UITableViewCellAccessoryDisclosureIndicator
箭頭

UITableViewCellAccessoryDetailDisclosureButton按鈕 + 箭頭

UITableViewCellAccessoryCheckmark 對(duì)勾

UITableViewCellAccessoryNone 沒有

UITableViewCellAccessoryDetaiButton 嘆號(hào)按鈕

Cell的常見屬性

設(shè)置cell的背景顏色 backgroundColor優(yōu)先級(jí)低于backgroundView

backgroundView使用方法:

創(chuàng)建一個(gè)View

UIView *bg = [[UIView alloc] init];

設(shè)置view的顏色,然后簡介的給cell賦值

bg.backgroundColor = [UIColor redColor];

再設(shè)置cell背景的顏色

cell.backgroundView= bg;

selectedBackgroundView使用方法:

創(chuàng)建一個(gè)View(也可以設(shè)置UIImageView作為cell的背景顏色)

UIView *selectedView= [[UIView alloc] init];

設(shè)置view的顏色,然后間接的賦值給cell

selectedView.backgroundColor = [UIColor redColor];

最后設(shè)置cell的背景顏色

cell.selectedBackgroundView= sele

還可以通過cell的accessoryView屬性來自定義輔助指示視圖(比如往右邊放一個(gè)開關(guān))

注意:這里的cell的指的是通過UITableViewCell創(chuàng)建的一個(gè)對(duì)象的accessoryView屬性來自定義輔助的視圖

Cell.accessoryView= UITableViewCellAccessoryCheckmark;

cell.accessoryView = [UIbutton alloc]init];(可以在右邊自定義控件可以放一個(gè)按鈕或者一個(gè)開關(guān))

5.png

注意:以上cell的屬性包含了4個(gè)屬性

Cell的重用原理

iOS設(shè)備的內(nèi)存有限,如果用UITableView顯示成千上萬條數(shù)據(jù),就需要成千上萬個(gè)UITableViewCell對(duì)象的話,那將會(huì)耗盡iOS設(shè)備的內(nèi)存。要解決該問題,需要重用UITableViewCell對(duì)象

重用原理:當(dāng)滾動(dòng)列表時(shí),部分UITableViewCell會(huì)移出窗口,UITableView會(huì)將窗口外的UITableViewCell放入一個(gè)對(duì)象池中,等待重用。當(dāng)UITableView要求dataSource返回UITableViewCell時(shí),dataSource會(huì)先查看這個(gè)對(duì)象池,如果池中有未使用的UITableViewCell,dataSource會(huì)用新的數(shù)據(jù)配置這個(gè)UITableViewCell,然后返回給UITableView,重新顯示到窗口中,從而避免創(chuàng)建新對(duì)象

還有一個(gè)非常重要的問題:有時(shí)候需要自定義UITableViewCell(用一個(gè)子類繼承UITableViewCell),而且每一行用的不一定是同一種UITableViewCell,所以一個(gè)UITableView可能擁有不同類型的UITableViewCell,對(duì)象池中也會(huì)有很多不同類型的UITableViewCell,那么UITableView在重用UITableViewCell時(shí)可能會(huì)得到錯(cuò)誤類型的UITableViewCell

解決方案:UITableViewCell有個(gè)NSString
*reuseIdentifier屬性,可以在初始化UITableViewCell的時(shí)候傳入一個(gè)特定的字符串標(biāo)識(shí)來設(shè)置reuseIdentifier(一般用UITableViewCell的類名)。當(dāng)UITableView要求dataSource返回UITableViewCell時(shí),先通過一個(gè)字符串標(biāo)識(shí)到對(duì)象池中查找對(duì)應(yīng)類型的UITableViewCell對(duì)象,如果有,就重用,如果沒有,就傳入這個(gè)字符串標(biāo)識(shí)來初始化一個(gè)UITableViewCell對(duì)象

Cell的重用代碼

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

{

注意:重用機(jī)制是根據(jù)相同的標(biāo)識(shí)符來重用cell,標(biāo)識(shí)符不同的cell不能彼此重用

1.定義一個(gè)cell的標(biāo)識(shí)為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:注冊(cè)

      另一中性能優(yōu)化的寫法:

      0.先確定cell的重用標(biāo)識(shí)

      1.注冊(cè)帶重用標(biāo)識(shí)的cell

      2.從緩存池中取是否有帶重用標(biāo)識(shí)的cell(如果沒有,系統(tǒng)會(huì)根據(jù)注冊(cè)自動(dòng)創(chuàng)建一個(gè)相應(yīng)的cell返回給我們)

      3.覆蓋cell上面的數(shù)據(jù)

      說明:當(dāng)cell離開屏幕的時(shí)候,就會(huì)放到tableView的緩存池中,這時(shí)候緩存池才有數(shù)據(jù)


  



         3.0 先確定cell的重用標(biāo)識(shí):命名規(guī)范:cell類型+ID

        static NSString *ID = @"carID"; // static修飾局部變量,局部變量從執(zhí)行后始終存在,

但不能被其它函數(shù)使用, 當(dāng)再次進(jìn)入該函數(shù)時(shí), 將保存上次的結(jié)果。其它與局部變量一樣。

  static BOOL isReged =NO;

         3.1 先注冊(cè)帶ID的cell

 
  if (isReged ==NO) {

warning registerCell需要注意的3點(diǎn),面試可能會(huì)問到

該方法是伴隨著UICollectionView出現(xiàn)的,也就是iOS6出現(xiàn)的

采用注冊(cè)創(chuàng)建出來的cell,默認(rèn)是Default樣式,所以一般注冊(cè)大部分都用在自定義cell的時(shí)候

需要注意的是 [tableView registerNib:<#(UINib *)#>
forCellReuseIdentifier:<#(NSString *)#>] 是iOS5出現(xiàn)的

     編碼規(guī)范:xib自定義cell一般用注冊(cè)

 
          [tableView

registerClass:[UITableViewCell class] forCellReuseIdentifier:ID];

          isReged =YES;


             

 
      }


    

         3.2 查看緩存池中是否有帶重用標(biāo)識(shí)的cell

         緩存池方法中封裝了,如果緩存池中沒有,就根據(jù)注冊(cè)創(chuàng)建新的cell,然后返回給我們一個(gè)帶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)識(shí)

              1.將storyboard中的tableView中的cell的重用標(biāo)志賦值

              2.從緩存池中取是否有帶重用標(biāo)識(shí)的cell

              (2.1

如果沒有,系統(tǒng)會(huì)根據(jù)注冊(cè)自動(dòng)創(chuàng)建一個(gè)相應(yīng)的cell返回給我們;

              2.2 如果也沒有注冊(cè)過,系統(tǒng)會(huì)根據(jù)storyboard中寫好的帶重用標(biāo)志的cell來自動(dòng)創(chuàng)建,然后返回)

              3.覆蓋cell上面的數(shù)據(jù)

              說明:當(dāng)cell離開屏幕的時(shí)候,就會(huì)放到tableView的緩存池中,這時(shí)候緩存池才有數(shù)據(jù)

3.返回每行內(nèi)容:該方法,只有當(dāng)cell顯示在屏幕上的時(shí)候才會(huì)調(diào)用,是一種懶加載的思想

warning 如果有注冊(cè),就不會(huì)觸發(fā)storyboard的創(chuàng)建新cell的機(jī)制.只有沒有注冊(cè)過,并且storyboard中沒有標(biāo)記相應(yīng)cell 的時(shí)候,dequeueReusableCellWithIdentifier才會(huì)返回nil

- (UITableViewCell *)tableView:(UITableView *)tableView

cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

             3.0 先確定cell的重用標(biāo)識(shí):命名規(guī)范:數(shù)據(jù)的模型+ID


          static NSString *ID

= @"carID"; static修飾局部變量,局部變量只會(huì)分配一次內(nèi)存地址

             3.1 查看緩存池中是否有帶重用標(biāo)識(shí)的cell

             緩存池方法中封裝了,如果緩存池中沒有,就根據(jù)注冊(cè)創(chuàng)建新的cell,然后返回給我們一個(gè)帶ID的cell

             后面還封裝了一層,如果也沒有注冊(cè)呢,會(huì)根據(jù)storyboard中是否標(biāo)記了在重用cell,來創(chuàng)建一個(gè)新的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封裝一個(gè)view的步驟

新建一個(gè)xib文件描述一個(gè)view的內(nèi)部結(jié)構(gòu)(假設(shè)叫做MJTgCell.xib)

新建一個(gè)自定義的類

(自定義類需要繼承自系統(tǒng)自帶的view, 繼承自哪個(gè)類, 取決于xib根對(duì)象的Class)

新建類的類名最好跟xib的文件名保持一致(比如類名就叫做MJTgCell)

將xib中的控件 和 自定義類的.m文件 進(jìn)行連線

提供一個(gè)類方法返回一個(gè)創(chuàng)建好的自定義view(屏蔽從xib加載的過程)

提供一個(gè)模型屬性讓外界傳遞模型數(shù)據(jù)

重寫模型屬性的setter方法,在這里將模型數(shù)據(jù)展示到對(duì)應(yīng)的子控件上面

Delegate的使用場合

對(duì)象A內(nèi)部發(fā)生了一些事情,想通知對(duì)象B

對(duì)象B想監(jiān)聽對(duì)象A內(nèi)部發(fā)生了什么事情

對(duì)象A想在自己的方法內(nèi)部調(diào)用對(duì)象B的某個(gè)方法,并且對(duì)象A不能對(duì)對(duì)象B有耦合依賴

對(duì)象A想傳遞數(shù)據(jù)給對(duì)象B

……

以上情況,結(jié)果都一樣:對(duì)象B是對(duì)象A的代理(delegate)

使用delegate的步驟

先搞清楚誰是誰的代理(delegate)

定義代理協(xié)議,協(xié)議名稱的命名規(guī)范:控件類名+ Delegate

定義代理方法

代理方法一般都定義為@optional

代理方法名都以控件名開頭

代理方法至少有1個(gè)參數(shù),將控件本身傳遞出去

設(shè)置代理(delegate)對(duì)象 (比如myView.delegate = xxxx;)

代理對(duì)象遵守協(xié)議

代理對(duì)象實(shí)現(xiàn)協(xié)議里面該實(shí)現(xiàn)的方法

在恰當(dāng)?shù)臅r(shí)刻調(diào)用代理對(duì)象(delegate)的代理方法,通知代理發(fā)生了什么事情

(在調(diào)用之前判斷代理是否實(shí)現(xiàn)了該代理方法)

通過代碼自定義cell(cell的高度不一致)

1.新建一個(gè)繼承自UITableViewCell的類

注意:一個(gè)是初始化方法一個(gè)設(shè)置子控件的方法一個(gè)是設(shè)置數(shù)據(jù)的對(duì)象的set方法

2.重寫initWithStyle:reuseIdentifier:方法

添加所有需要顯示的子控件(不需要設(shè)置子控件的數(shù)據(jù)和frame, 子控件要添加到contentView中

進(jìn)行子控件一次性的屬性設(shè)置(有些屬性只需要設(shè)置一次, 比如字體\固定的圖片等等但是設(shè)置frame不行)

3.提供2個(gè)模型

數(shù)據(jù)模型: 存放文字?jǐn)?shù)據(jù)\圖片數(shù)據(jù)
(字典轉(zhuǎn)模)

frame模型: 存放數(shù)據(jù)模型\所有子控件的frame\cell的高度

4.cell擁有一個(gè)frame模型(不要直接擁有數(shù)據(jù)模型)

5.重寫frame模型屬性的setter方法: 在這個(gè)方法中設(shè)置子控件的顯示數(shù)據(jù)和frame

6.frame模型數(shù)據(jù)的初始化已經(jīng)采取懶加載的方式(每一個(gè)cell對(duì)應(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左邊放一個(gè)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)先級(jí)低于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 對(duì)號(hào)

UITableViewCellAccessoryDetailButton NS_ENUM_AVAILABLE_IOS(7_0) // info button. tracks 圈!

 設(shè)置輔助視圖

 accessoryView優(yōu)先級(jí)高

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)建一個(gè)新的數(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ù),只需要對(duì)懶加載中的數(shù)據(jù)進(jìn)行操作即可

實(shí)際開發(fā)中,所用的數(shù)據(jù)也是從服務(wù)器拿到后展示

分析模型的創(chuàng)建

  • 組頭

  • 組尾

  • cell上的內(nèi)容(數(shù)組)

  • 每個(gè)cell上的內(nèi)容分為name和icon

  • 創(chuàng)建hero模型

單組數(shù)據(jù)展示

  • 數(shù)據(jù)源方法:返回多少組可以不實(shí)現(xiàn)
  • cell上自帶3個(gè)展示信息的子控件

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)建對(duì)應(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)先級(jí)比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,   
      // 小對(duì)勾checkmark. doesn't track

 UITableViewCellAccessoryDetailButton

NS_ENUM_AVAILABLE_IOS(7_0) // 圈i info button. tracks

*/

 cell的輔助視圖樣式

cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

 cell的輔助視圖,作用優(yōu)先級(jí)高于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)先級(jí)高于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上

常見代理/易錯(cuò)屬性

  • 前兩者易錯(cuò)

選中某一行時(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返回對(duì)應(yīng)的高度

(CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

if (indexPath.row == 0) {

return 222;

}

return 88;

}

  • 分割線樣式的枚舉容易寫錯(cuò)

warning 在設(shè)置分割線樣式為None的時(shí)候如果無效,先看你是否搞混了下列2個(gè)枚舉

/*

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)識(shí)

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;

}

  • 注冊(cè)封裝
  • (instancetype)cellWithTableView:(UITableView
    *)tableView

{

 確定重用標(biāo)示(規(guī)范的寫法)

static NSString *ID = nil;

if (ID == nil)
{

ID = [NSString stringWithFormat:@"%@ID",
NSStringFromClass(self)];

}



 如果沒有注冊(cè)過,就注冊(cè)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 的原因是為了拖個(gè)代碼塊

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;

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容