基礎 (十五) : UITableView

掌握

設置UITableView的dataSource、delegate

UITableView多組數據和單組數據的展示

UITableViewCell的常見屬性

UITableView的性能優化(cell的循環利用)

自定義Cell

什么是UITableView?

能看到各式各樣的表格數據就是UITableView

1.png
2.png

如何展示數據

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的數據更新到最新狀態。

*/


3.png

tableView展示數據的過程

調用數據源的下面方法得知一共有多少組數據

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

調用數據源的下面方法得知每一組有多少行數據

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

調用數據源的下面方法得知每一行顯示什么內容

  • (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
4.png

初始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];(可以在右邊自定義控件可以放一個按鈕或者一個開關)

5.png

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

}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容