表視圖是iOS開發中使用最頻繁的視圖,我們一般都會選擇以表的形式來展現數據,比如通訊錄、頻道列表等。表視圖分段、分組、索引等功能使我們所展示的數據看起來更規整更有調理,更令人興奮的是表視圖還可以利用細節展示等功能多層次的展示數據,正所謂一表勝千言。 不過,相較於其它控件表視圖的使用比較復雜,但是對比於表視圖各種靈活多變的功能,我們在使用上花費的努力還是相當值得的。
簡單表視圖 表視圖的形式靈活多變,本著由淺入深的原則,我們先從簡單表視圖開始學習。本節講的簡單表視圖是動態表,(iOS 5之前全部是動態表沒有動態表和靜態表區別)。 創建簡單表視圖 在iOS 5之後我們可以使用xib或者故事板技術創建表視圖,要顯示的是一個最基本的表,我們只需實現UITableViewDataSource協議中必須要實現的方法即可,分別是tableView:numberOfRowsInSection:和tableView:cellForRowAtIndexPath:就可以了。: 構造方法initWithFrame:style:是在實例化表視圖的時候調用,如果采用xib或故事板來設計表視圖,那麼表視圖的創建是在實例化表視圖控制器的時候完成的,表視圖顯示的時候會發出tableView:numberOfRowsInSection:消息詢問當前節中的行數,表視圖單元格顯示的時候會發出tableView:cellForRowAtIndexPath:消息為單元格提供顯示數據。 我們創建一個簡單表視圖,單元格使用默認樣式,有圖標和主標題,顯示的是世界杯球隊的信息。 使用“Single View Application”模板創建一個工程,工程名為“SimpleTable”,打開IB設計畫面,在“View Controller Scene”選中“View Controller”刪除控制器,然後從控件庫中拖拽一個“Table View Controller”到設計畫面。 將h文件中ViewController的父類從原來的UIViewController修改為UITableViewController。 在IB設計畫面左側的Scene列表中選擇“Table View Controller Scene” → “Table View Controller”, 打開表視圖控制器的標識檢查器,在Class選項裡選擇“ViewController”,這是我們自己的編寫視圖控制器。 然後在Scene列表中選擇“Table View Controller Scene” → “Table View Controller” → “Table View”, 打開表視圖的屬性檢查器。Content下有兩個選項“Dynamic Prototypes”和“Static Cells”,這兩個選項只有在故事板中才有。“Dynamic Prototypes”是構建“動態表” 如果通過代碼來實現單元格的創建,“Prototype Cells”項目要設為0,代碼實現的模式代碼如下: [cpp] static NSString *CellIdentifier = @”CellIdentifier”; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } static NSString *CellIdentifier = @”CellIdentifier”; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } Identifier是可重用單元格標識符,這個可重用單元格與Collection視圖中的可重用單元格概念一樣。首先,在表視圖中查找是否有可以重用的單元格,如果沒有就通過initWithStyle: reuseIdentifier:構造方法創建一個單元格對象。 如果要利用故事板設計單元格,要選擇“Table View Controller Scene” → “Table View Controller” → “Table View” → “Table View Cell”,打開單元格的屬性檢查器,Style下有很多選項, Identifier是指可重用單元格標識符。 這樣操作以後在代碼部分就不需要實例化單元格了,我們直接通過設定的Identifier取得單元格的實例,以此達到重用單元格的目的。 [cpp] static NSString *CellIdentifier = @”CellIdentifier”; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } 我們需要將“team.plist”和“球隊圖片”添加到工程中,ViewController.h文件的代碼如下: #import <UIKit/UIKit.h> @interface ViewController : UITableViewController @property (nonatomic, strong) NSArray *listTeams; @end static NSString *CellIdentifier = @”CellIdentifier”; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } 我們需要將“team.plist”和“球隊圖片”添加到工程中,ViewController.h文件的代碼如下: #import <UIKit/UIKit.h> @interface ViewController : UITableViewController @property (nonatomic, strong) NSArray *listTeams; @end 需要將ViewController的父類修改為UITableViewController。還定義NSArray*類型的屬性listTeams,listTeams用來裝載從文件中讀取的數據。讀取屬性列表文件team.plist的操作是在viewDidLoad方法中實現的 ViewController.m文件的viewDidLoad方法代碼如下: [cpp] - (void)viewDidLoad { [super viewDidLoad]; NSBundle *bundle = [NSBundle mainBundle]; NSString *plistPath = [bundle pathForResource:@"team" ofType:@"plist"]; //獲取屬性列表文件中的全部數據 self.listTeams = [[NSArray alloc] initWithContentsOfFile:plistPath]; } 我們再看看UITableViewDataSource協議方法,代碼如下: - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.listTeams count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @”CellIdentifier”; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } NSUInteger row = [indexPath row]; NSDictionary *rowDict = [self.listFilterTeams objectAtIndex:row]; cell.textLabel.text = [rowDict objectForKey:@"name"]; NSString *imagePath = [rowDict objectForKey:@"image"]; imagePath = [imagePath stringByAppendingString:@".png"]; cell.imageView.image = [UIImage imageNamed:imagePath]; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; return cell; } - (void)viewDidLoad { [super viewDidLoad]; www.2cto.com NSBundle *bundle = [NSBundle mainBundle]; NSString *plistPath = [bundle pathForResource:@"team" ofType:@"plist"]; //獲取屬性列表文件中的全部數據 self.listTeams = [[NSArray alloc] initWithContentsOfFile:plistPath]; } 我們再看看UITableViewDataSource協議方法,代碼如下: - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.listTeams count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @”CellIdentifier”; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } NSUInteger row = [indexPath row]; NSDictionary *rowDict = [self.listFilterTeams objectAtIndex:row]; cell.textLabel.text = [rowDict objectForKey:@"name"]; NSString *imagePath = [rowDict objectForKey:@"image"]; imagePath = [imagePath stringByAppendingString:@".png"]; cell.imageView.image = [UIImage imageNamed:imagePath]; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; return cell; } 由於當前的這個表事實上只有一個節,因此不需要對節進行區分,在tableView: numberOfRowsInSection:方法中直接返回listTeams屬性的長度即可。tableView:cellForRowAtIndexPath:方法中NSIndexPath參數的row方法可以獲得當前的單元格行索引。cell.accessoryType屬性是設置擴展視圖類型。 我們可以將單元格的樣式UITableViewCellStyleDefault替換為其它三種,來體驗一下其它的三種單元格樣式的效果。 簡單表案例運行結果