创建 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