SwiftUI-如何使用 ForEach 循环

258 阅读3分钟

在 SwiftUI 中,ForEach 是一个强大的视图容器,用于根据一个集合来生成一系列视图。

它可以在列表、栅格、动态布局等场景中使用。

ForEach 的作用类似于传统编程中的循环,但是它直接与 SwiftUI 的视图系统集成,可以轻松创建可视化的列表或动态生成视图。

ForEach 的基本概念

ForEach 接受一个数据集合(如数组或范围),并为集合中的每个元素生成一个子视图。

ForEach 需要两个关键参数:

  • 一个集合:可以是数组、范围或其他可以遍历的集合。
  • 一个闭包:定义如何为集合中的每个元素创建视图。

ForEach 的基本使用

使用范围 (Range)

这是最简单的用法,使用整数范围来生成视图。

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            ForEach(0..<5) { index in
                Text("Item \(index)")
                    .padding()
                    .background(Color.blue)
                    .foregroundColor(.white)
                    .cornerRadius(8)
            }
        }
    }
} 

在这个例子中,ForEach 创建了 5 个 Text 视图,显示了从 0 到 4 的索引。

使用数组

你可以使用数组来生成视图,每个元素在数组中对应一个视图。

import SwiftUI

struct ContentView: View {
    let names = ["Alice", "Bob", "Charlie", "Diana"]
    var body: some View {
        VStack {
            ForEach(names, id: \.self) { name in
                Text("Hello, \(name)!")
                    .padding()
                    .background(Color.green)
                    .foregroundColor(.white)
                    .cornerRadius(8)
            }
        }
    }
} 

在这个例子中,ForEach 生成了 4 个 Text 视图,每个视图显示数组中的一个名字。

标识符 (id)

在使用 ForEach 时,SwiftUI 需要知道每个视图的唯一标识符(ID),以便能够追踪和高效更新视图。

你可以显式地提供标识符,或者在数据类型符合 Identifiable 协议时,自动使用数据的 id 属性。

显式标识符

如果你的数据类型没有符合 Identifiable 协议,你需要显式地提供一个唯一标识符。

struct ContentView: View {
    let items = [
        Item(id: 1, name: "Item 1"),
        Item(id: 2, name: "Item 2"),
        Item(id: 3, name: "Item 3")
    ]
    
    var body: some View {
        VStack {
            ForEach(items, id: \.id) { item in
                Text(item.name)
                    .padding()
                    .background(Color.orange)
                    .foregroundColor(.white)
                    .cornerRadius(8)
            }
        }
    }
} 

struct Item {
    let id: Int
    let name: String
}

在这个例子中,每个 Item 的 id 被用作标识符。

自动标识符 (Identifiable)

如果你的数据类型符合 Identifiable 协议,SwiftUI 会自动使用数据的 id 属性。

struct ContentView: View {
    let items = [
        IdentifiableItem(name: "Item 1"),
        IdentifiableItem(name: "Item 2"),
        IdentifiableItem(name: "Item 3")
    ]

    var body: some View {
        VStack {
            ForEach(items) { item in
                Text(item.name)
                    .padding()
                    .background(Color.purple)
                    .foregroundColor(.white)
                    .cornerRadius(8)
            }
        }
    }
}

struct IdentifiableItem: Identifiable {
    let id = UUID()  // 自动生成唯一标识符
    let name: String
}

在这个例子中,IdentifiableItem 自动生成唯一的 id,无需在 ForEach 中显式指定。

动态视图的更新

ForEach 非常适合处理动态数据。当数据集合更新时,ForEach 会自动更新视图,确保界面始终与数据保持同步。

示例:动态添加元素

import SwiftUI

struct ContentView: View {
    @State private var items = ["Item 1", "Item 2", "Item 3"]
    var body: some View {
        VStack {
            ForEach(items, id: \.self) { item in
                Text(item)
                    .padding()
                    .background(Color.teal)
                    .foregroundColor(.white)
                    .cornerRadius(8)
            }
            Button("Add Item") {
                items.append("Item \(items.count + 1)")
            }
            .padding()
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
        }
    }
} 

在这个例子中,每次点击“Add Item”按钮时,都会向数组添加一个新元素,ForEach 会立即反映这一变化。

嵌套 ForEach

你可以嵌套 ForEach 来创建复杂的布局或视图层次结构。例如,生成一个表格布局:

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            ForEach(0..<3) { row in
                HStack {
                    ForEach(0..<3) { column in
                        Text("(\(row), \(column))")
                            .padding()
                            .background(Color.gray)
                            .foregroundColor(.white)
                            .cornerRadius(8)
                    }
                }
            }
        }
    }
} 

在这个例子中,嵌套的 ForEach 用于生成一个 3x3 的网格视图。

小结:

  • ForEach是SwiftUI中用于根据数据集合动态生成视图的容器。
  • 标识符确保SwiftUI可以高效地追踪和更新视图。
  • 动态更新:数据集合的变化会自动反映在UI上。
  • 嵌套使用:可以嵌套ForEach来创建复杂的布局。

通过使用ForEach,你可以轻松构建动态、可扩展的用户界面,特别适合需要根据数据生成视图的场景。