SwiftUI — Table

Table 是 SwiftUI 中用于展示多列数据的视图容器,特别适合 macOS 和 iPadOS 上的表格布局(类似于 UITableViewNSTableView)。以下是 Table 的体系结构和使用方法的详细介绍:


1. Table 的体系结构 #

核心组件 #

  • Table 容器:用于定义表格的整体结构和列布局。
  • TableColumn:定义表格的列,包括标题、数据绑定和内容渲染。
  • 数据源:通过集合(如数组)提供表格的行数据,通常结合 Identifiable 协议确保每行有唯一标识。

关键特性 #

  • 多列支持:支持动态列数和列排序。
  • 行选择:支持单行或多行选择(通过 selection 绑定)。
  • 排序:通过 sortComparator 实现列排序。
  • 样式:支持自定义行高、列宽和单元格内容。

2. 基本使用方法 #

步骤 1:定义数据模型 #

确保数据模型遵循 Identifiable 协议,以便每行有唯一标识。

struct Person: Identifiable {
    let id = UUID()
    var name: String
    var age: Int
    var email: String
}

步骤 2:创建 Table #

使用 Table 容器定义表格,并通过 TableColumn 定义列。

struct ContentView: View {
    @State private var people = [
        Person(name: "Alice", age: 30, email: "alice@example.com"),
        Person(name: "Bob", age: 25, email: "bob@example.com"),
        Person(name: "Charlie", age: 35, email: "charlie@example.com")
    ]
    
    var body: some View {
        Table(people) {
            TableColumn("Name", value: \.name)
            TableColumn("Age", value: \.age)
            TableColumn("Email", value: \.email)
        }
    }
}

3. 高级功能 #

(1) 自定义列内容 #

通过闭包自定义列的渲染逻辑。

TableColumn("Name") { person in
    HStack {
        Image(systemName: "person.circle")
        Text(person.name)
    }
}

(2) 行选择 #

通过 selection 绑定实现行选择(支持单行或多行)。

@State private var selectedPersonID: UUID?

Table(people, selection: $selectedPersonID) {
    TableColumn("Name", value: \.name)
    TableColumn("Age", value: \.age)
    TableColumn("Email", value: \.email)
}

(3) 排序 #

通过 sortComparator 实现列排序。

@State private var sortOrder = [KeyPathComparator(\Person.name)]

Table(people, sortOrder: $sortOrder) {
    TableColumn("Name", value: \.name)
    TableColumn("Age", value: \.age)
    TableColumn("Email", value: \.email)
}
.onChange(of: sortOrder) { newOrder in
    people.sort(using: newOrder)
}

(4) 动态列 #

根据条件动态生成列。

@State private var showEmailColumn = true

Table(people) {
    TableColumn("Name", value: \.name)
    TableColumn("Age", value: \.age)
    if showEmailColumn {
        TableColumn("Email", value: \.email)
    }
}

(5) 样式调整 #

通过 tableStyle 设置表格样式(如 .inset.bordered)。

Table(people) {
    TableColumn("Name", value: \.name)
    TableColumn("Age", value: \.age)
    TableColumn("Email", value: \.email)
}
.tableStyle(.inset)

4. 完整示例 #

以下是一个包含选择、排序和自定义列内容的完整示例:

struct ContentView: View {
    @State private var people = [
        Person(name: "Alice", age: 30, email: "alice@example.com"),
        Person(name: "Bob", age: 25, email: "bob@example.com"),
        Person(name: "Charlie", age: 35, email: "charlie@example.com")
    ]
    @State private var selectedPersonID: UUID?
    @State private var sortOrder = [KeyPathComparator(\Person.name)]
    
    var body: some View {
        VStack {
            Table(people, selection: $selectedPersonID, sortOrder: $sortOrder) {
                TableColumn("Name", value: \.name) { person in
                    HStack {
                        Image(systemName: "person.circle")
                        Text(person.name)
                    }
                }
                TableColumn("Age", value: \.age)
                TableColumn("Email", value: \.email)
            }
            .onChange(of: sortOrder) { newOrder in
                people.sort(using: newOrder)
            }
            .tableStyle(.inset)
            
            if let selectedID = selectedPersonID, let person = people.first(where: { $0.id == selectedID }) {
                Text("Selected: \(person.name)")
            }
        }
        .padding()
    }
}

5. 注意事项 #

  1. 平台支持
    • Table 主要用于 macOS 和 iPadOS,iOS 上通常使用 ListLazyVStack 替代。
  2. 性能优化
    • 对于大数据集,确保数据模型轻量,避免复杂计算或渲染逻辑。
  3. 样式限制
    • Table 的样式定制能力有限,复杂需求可能需要自定义视图或结合 AppKit/UIKit。

6. 对比其他组件 #

组件适用场景特点
Table多列数据展示(macOS/iPadOS)支持排序、选择、动态列,适合复杂表格。
List单列数据展示(全平台)简单易用,支持 Section 和动态内容。
LazyVStack自定义布局(全平台)灵活但需手动管理布局和性能优化。

通过 Table,你可以快速构建功能丰富的表格视图,适用于数据密集型的 macOS 和 iPadOS 应用。

本文共 990 字,上次修改于 Feb 3, 2025