基礎(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需要一個數(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)。

*/


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ì)思想,貫穿于整個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))

5.png

注意:以上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;

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內(nèi)容