Structure¶
ForEach¶
Creates views from a collection of identified data.¶
Declaration¶
struct ForEach<Data, ID, Content> where Data : RandomAccessCollection, ID : Hashable
Overview¶
ForEach supports three identifiers:
- init(_:content:), for iterating over a range
- init(_:content:), for iterating over data that conforms to identifiable
- init(_:id:content:) for iterating over that can be identified, but does not conform to identifiable
Iterating over a range¶
This initializer is ForEach's most trivial. It is analogous to a common for loop.
struct ExampleView: View {
let myFruits: [String] = ["🍌🍌", "🍑🍑", "🍎🍎"]
var body: some View {
VStack {
ForEach(0..<myFruits.count) { index in
Text(myFruits[index])
}
}
}
}

Notice however, that this view is only rendered once. Therefore, if myFruits.count changes, the view will not update. For example, clicking New Fruit in the following code returns the error:
ForEach(_:content:) should only be used for constant data.
struct ErrorView: View {
@State var myFruits: [String] = ["🍌🍌", "🍑🍑", "🍎🍎"]
var body: some View {
Button("New Fruit") {
newFruit()
}
VStack {
ForEach(0..<myFruits.count) { index in
Text(myFruits[index])
}
}
}
func newFruit() {
let allFruit: [String] = ["🍏🍏", "🍒🍒", "🍓🍓", "🥝🥝", "🥭🥭", "🍊🍊", "🍍🍍"]
myFruits.append(allFruit.randomElement()!)
}
}

The instance only reads the initial value of the provided data and doesn't need to identify views across updates. To compute views on demand over a dynamic range, use init(_:id:content:).
Iterating over Identifiable data¶
If your data does not conform to identifiable, use init(_:id:content:).
Note: if your data does not conform to identifiable you will receive the following error:
Initializer 'init(_:rowContent:)' requires that ‘SomeType’ conform to 'Identifiable'
An array of primitive types, such as strings & ints, will throw this error. Identify these items with id: .self
– because they themselves can be used as the identifiable object. See more in init(_:id:content:).
struct ExampleView: View {
let myFruits: [Fruit] = [
Fruit(emoji: "🍌🍌", name: "Banana"),
Fruit(emoji: "🍑🍑", name: "Peach"),
Fruit(emoji: "🍎🍎", name: "Apple")
]
var body: some View {
VStack {
ForEach(myFruits) { fruit in
Text(fruit.name + fruit.emoji)
}
}
}
}
struct Fruit: Identifiable {
var emoji: String
var name: String
// Create a unique ID for our object
// This idea allows Fruit to conform to Identifiable
let id = UUID()
}

Explicitly identifying data¶
For data that does not conform to Identifiable, use this initializer.
A very common use case for this initialier is iterating over primitive data, such as strings or ints. In the following example, the fruit string is used as the identifiable unit.
struct ExampleView: View {
let myFruits: [String] = ["🍌🍌", "🍑🍑", "🍎🍎"]
var body: some View {
ForEach(myFruits, id:\.self) { fruit in
HStack {
Text(fruit)
}
}
}
}

This initializer can also be used with objects that don't conform to Identifiable, but have identifiable properties. For example:
struct ExampleView: View {
let myFruits: [Fruit] = [
Fruit(emoji: "🍌🍌", name: "Banana"),
Fruit(emoji: "🍑🍑", name: "Peach"),
Fruit(emoji: "🍎🍎", name: "Apple")
]
var body: some View {
ForEach(myFruits, id: \.emoji) { fruit in
HStack {
Text(fruit.name + fruit.emoji)
}
}
}
}
struct Fruit {
var emoji: String
var name: String
}

Notice, this initializer can be used for data that can change. For example:
struct ExampleView: View {
@State var myFruits: [String] = ["🍌🍌", "🍑🍑", "🍎🍎"]
var body: some View {
Button("New Fruit") {
newFruit()
}
ForEach(myFruits, id: \.self) { fruit in
HStack {
Text(fruit)
}
}
}
func newFruit() {
let allFruit: [String] = ["🍏🍏", "🍒🍒", "🍓🍓", "🥝🥝", "🥭🥭", "🍊🍊", "🍍🍍"]
myFruits.append(allFruit.randomElement()!)
}
}

- Note: This initializer works well for externally loaded data. It enables your app's frontend to automatically reflect data as it arrives.
Availability¶
iOS 13.0+
macOS 10.15+
tvOS 13.0+
watchOS 6.0+
Topics¶
Instance Property¶
content A function you can use to create content on demand using the underlying data
data The collection of underlying identified data that SwiftUI uses to create views dynamically.
Initializer¶
init(_:content:) Creates a view from data that conforms to Identifiable.
init(_:content:) Computes views over a given constant range.
init(_:id:content:) Creates an instance that uniquely identifies and computes views.
Type Alias¶
Body The type of view representing the body of this view.