ForEachとforEachの違い

はじめに

紛らわしいタイトルだな…… 大文字小文字の差ではないですよ!

SwiftUIでListを作るときに、ForEachというものが出てきました。たしか、Swiftにも繰り返し構文としてforEachがありました。
似ている……!!?

Swiftで使うforEach

これはおなじみですね。
配列の中身を順次取り出して処理するときに使います。

配列.forEach {
    取り出した値の処理
    (取り出した値は$0で参照可能)
}

SwiftUIで使うForEach

これはViewを繰り返し作るときに使います。先に出てきたListやVStackなどのコンテナビューの中で使います。与えられたデータを順次取り出してViewを作ります。

Listなどのコンテナビュー {
    ForEach(配列) {
        繰り返し生成するViewをここで作る
        (取り出した値は$0で参照可能)
    }
}

なおここでの「配列」はIdentifiableプロトコルに準拠したデータの配列である必要があります。準拠していなければ、配列の要素が一意であることを示せるプロパティを明示しないといけません。

Listなどのコンテナビュー {
    ForEach(配列, id:一意性を示せるプロパティ) {
        繰り返し生成するViewをここで作る
        (取り出した値は$0で参照可能)
    }
}

取り出した値はクロージャを使って扱うことも可能。

ForEach(配列, id: 一意性を示せるプロパティ) { 配列から取り出した要素を入れる変数 in
    $0ではなく、配列から取り出した要素を入れる変数名で参照できる
}

いちいちIdentifiableプロトコルに準拠したデータを作るのが面倒なとき

String型の配列とか加工せずにそのまま使いたいよね。
そういうときは、一意性を示せるプロパティとして自分自身を渡せばいいんじゃないかと思います多分。ただ、上記のString型の配列などは要素の重複が可能なので、その確認は必要ですね。

状況によりけりですが、素直に一意性を示せるプロパティを持たせておくのが定石かもしれません。

参考:Identifiableプロトコル

Identifiable – Swift Standard Library | Apple Developer Documentation 曰く、
A class of types whose instances hold the value of an entity with stable identity.

このプロトコルに準拠した構造体/クラスは変数idという一意な値を持っています。変数名はidで固定であり、一意性を保証できるなら持たせる値は何でもいいようです。
UUIDあたりが無難?