# ForEach examples

{% tabs %}
{% tab title="range" %}
### Loop over a <mark style="color:red;">range</mark> of integers

```swift
// init(
//     _  data: Range<Int>, 
//     content: @escaping (Int) -> Content
// )
// ---------------------------------------
// ForEach<Range<Int>, Int, Text>
// Data    = Range<Int>
// ID      = Int
// Content = Text
struct ContentView: View {
    let positions = ["First", "Second", "Third"]

    var body: some View {
        ForEach(0..<positions.count) { index in
            Text(positions[index])
        }
    }
}
```
{% endtab %}

{% tab title="data" %}
### Loop over any <mark style="color:red;">data</mark>

Loop over an **array of strings** and specified `\.self` key path, which refers to the **string** itself as an **identifier**.

```swift
// init(
//     _  data: Data, 
//     id     : KeyPath<Data.Element, ID>, 
//     content: @escaping (Data.Element) -> Content
// )
// ------------------------------------------------
// ForEach<[String], String, Text>
// Data    = [String]
// ID      = String
// Content = Text
struct ContentView: View {
    
    let coworkers = [
        "Gabriel Lang", "John Brunelle", "Matthew Arieta", "Wayne Ohmer", 
        "Ralph Dugue", "Alex Burnett", "Craig Heneveld", "Bill Munsell"
    ]
            
    var body: some View {
        VStack {
            ForEach(coworkers, id: \.self) { name in
                Text(name)
            }
        }
    }
}
```
{% endtab %}

{% tab title="custom type" %}
### Loop over <mark style="color:red;">custom type</mark>.

```swift
// custom type
struct Position {
    let id  : Int
    let name: String
}

// loop over custom type
struct ContentView: View {

    let positions = [
        Position(id: 1, name: "First"),
        Position(id: 2, name: "Second"),
        Position(id: 3, name: "Third")
    ]

    var body: some View {        
        ForEach(positions, id: \.id) { position in
            Text(position.name)
        }
    }
}

// ForEach<[Position], Int, Text>
// ------------------------------
// Data    = [Position]
// ID      = Int
// Content = Text
```
{% endtab %}

{% tab title="identifiable" %}
### Loop over <mark style="color:purple;">Identifiable</mark> data

The last one is the most compact form of all three, but it required each element in a collection to conform [`Identifiable`](https://developer.apple.com/documentation/swift/identifiable) protocol.

```swift
extension ForEach where 
    ID == Data.Element.ID, 
    Content     : View, 
    Data.Element: Identifiable 
{
    public init(
        _ data: Data, 
        @ViewBuilder content: @escaping (Data.Element) -> Content
    )
}
```

上面例子中的自訂型別稍微改一下，就可以使用這個 initializer。

```swift
// conform to `Identifiable`
struct Position: Identifiable {
    let id: Int
    let name: String
}

// loop over Identifiable data
struct ContentView: View {

    let positions = [
        Position(id: 1, name: "First"),
        Position(id: 2, name: "Second"),
        Position(id: 3, name: "Third")
    ]

    var body: some View {        
        ForEach(positions) { position in
            Text(position.name)
        }
    }
}

// ForEach<[Position], Int, Text>
// ------------------------------
// Data    = [Position]
// ID      = Int
// Content = Text
```
{% endtab %}

{% tab title="👥 相關" %}
* examples for [](<> "mention").
{% endtab %}
{% endtabs %}
