建立 UITableView

表檢視是可以選擇的行列表。每行都是從資料來源填充的。此示例建立一個簡單的表檢視,其中每行是單行文字。

StackOverflow 文件

在故事板中新增 UITableView

儘管有許多方法可以建立 UITableView,但最簡單的方法之一是在 Storyboard 中新增一個。開啟你的故事板並將 UITableView 拖到你的 UIViewController 上。確保使用自動佈局正確對齊工作臺(將所有四個邊都固定)。

用資料填充表格

為了在表檢視中動態顯示內容(即從陣列源,核心資料模型,網路伺服器等資料來源載入),你需要設定資料來源。

建立一個簡單的資料來源

如上所述,資料來源可以是包含資料的任何資料來源。它完全取決於你如何格式化它和它的內容。唯一的要求是你必須能夠稍後閱讀它,以便你可以在需要時使用資料填充表格的每一行。

在這個例子中,我們只是設定一個陣列,其中包含一些字串(文字)作為我們的資料來源:

迅速

let myDataArray: [String] = ["Row one", "Row two", "Row three", "Row four", "Row five"]

Objective-C

// You'll need to define this variable as a global variable (like an @property) so that you can access it later when needed.
NSArray *myDataArray = @[@"Row one", @"Row two", @"Row three", @"Row four", @"Row five"];

在 View Controller 中設定資料來源

確保你的檢視控制器符合 UITableViewDataSource 協議。

迅速

class ViewController: UIViewController, UITableViewDataSource {

Objective-C

@interface ViewController : UIViewController <UITableViewDataSource>

一旦你的檢視控制器宣告它將符合 UITableViewDataSource(這就是我們上面剛剛完成的),你需要在檢視控制器類中至少實現以下方法:

  • tableView:numberOfRowsInSection,這會詢問你的表檢視應該有多少行。

    // Swift    
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
         return self.myDataArray.count
    }
    
  • tableView:cellForRowAtIndexPath,請求你為 tableView:numberOfRowsInSection 中指定的每一行建立並返回一個單元格。因此,如果你說需要 10 行,則每行呼叫此方法十次,並且你需要為每個行建立一個單元格。

    // Swift    
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
         // Create a new cell here. The cellReuseIdentifier needs to match the reuse identifier from the cell in your Storyboard
         let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellReuseIdentifier) as UITableViewCell!
    
         // Set the label on your cell to the text from your data array
         cell.textLabel?.text = self.myDataArray[indexPath.row]
    
         return cell
     }
    

警告 : 對於 cellForRowAtIndexPath:中的任何單元格,你不能返回 nil。這將導致你的應用程式崩潰,你將在控制檯中看到以下錯誤:

Uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'

將表檢視的資料來源連線到檢視控制器

你可以通過在檢視控制器上將表的 dataSource 屬性設定為 self 來通過程式碼執行此操作。或者你可以在你的故事板中選擇你的表檢視,開啟屬性檢查器中,選擇 dataSource奧特萊斯面板,然後拖動到你的檢視控制器( :請確保你連線到的 UIViewController,不是一個 UIView 或其他物體你的 UIViewController 中)。

處理行選擇

當使用者點選表格檢視中的某一行時,通常情況下,你需要做一些事情 - 要做出迴應。在許多應用中,當你點按一行時,會顯示有關你點按的專案的詳細資訊。想想訊息應用程式:當你點選顯示某個聯絡人的行時,與該人的對話將顯示在螢幕上。

要做到這一點,你必須遵守 UITableViewDelegate 協議。這樣做符合資料來源協議。但是這一次,你只需將它新增到 UITableViewDataSource 旁邊並用逗號分隔。所以看起來應該是這樣的:

迅速

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

Objective-C

@interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>

沒有必要的方法來實現表檢視的委託。但是,要處理行選擇,你需要使用以下方法:

  • tableView:didSelectRowAtIndexPath,只要輕敲一行就會呼叫它,這樣就可以做出響應。對於我們的示例,我們只需在 Xcode 日誌中列印確認宣告。

    // Swift    
    
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
         print("You tapped cell number \(indexPath.row).")
     }
    
    // Objective-C    
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
         NSLog(@"You tapped cell number %ld.", (long)indexPath.row);
    }
    

最終的解決方案

請參閱下面的完整設定,僅提供程式碼,無需解釋。

迅速

import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    // Data model: These strings will be the data for the table view cells
    let myDataArray: [String] = ["Row one", "Row two", "Row three", "Row four", "Row five"]

    // cell reuse id (cells that scroll out of view can be reused) 
    let cellReuseIdentifier = "cell"

    // don't forget to hook this up from the storyboard
    @IBOutlet var myTableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Register the table view cell class and its reuse id
        myTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)

        // This view controller itself will provide the delegate methods and row data for the table view.
        myTableView.delegate = self
        myTableView.dataSource = self
    }
    
    // number of rows in table view
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.myDataArray.count
    }
    
    // create a cell for each table view row
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        // create a new cell if needed or reuse an old one
        let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellReuseIdentifier) as UITableViewCell!

        // set the text from the data model
        cell.textLabel?.text = self.myDataArray[indexPath.row]
        
        return cell
    }
    
    // method to run when table view cell is tapped
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        print("You tapped cell number \(indexPath.row).")
    }
}

Objective-C

ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController: UIViewController <UITableViewDelegate, UITableViewDataSource> {
    IBOutlet UITableView *myTableView;
    NSArray *myDataArray;
}

@end

ViewController.m

#import "ViewController.h"

// cell reuse id (cells that scroll out of view can be reused)
NSString * _Nonnull cellReuseIdentifier = @"cell";

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Data model: These strings will be the data for the table view cells
    myDataArray = @[@"Row one", @"Row two", @"Row three", @"Row four", @"Row five"];
    
    // Register the table view cell class and its reuse id
    [myTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellReuseIdentifier];
    
    // This view controller itself will provide the delegate methods and row data for the table view.
    myTableView.delegate = self;
    myTableView.dataSource = self;
}

// number of rows in table view
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return myDataArray.count;
}

// create a cell for each table view row
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // create a new cell if needed or reuse an old one
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellReuseIdentifier];
        
    // set the text from the data model
    cell.textLabel.text = myDataArray[indexPath.row];
    
    return cell;
}
    
// method to run when table view cell is tapped
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    NSLog(@"You tapped cell number %ld.", (long)indexPath.row);
}

@end