(2023/09/18 更新)
ForEachは繰り返し処理の中で、Viewを生成する仕組みです。文字列の入った配列をループしてそれぞれをTextViewに変換する、またはメニュー項目に追加するような動きを実現します。さらに、ForEachを使用すると、手動でViewを追加した際の10個までの制限を回避できます。
ForEachの繰り返しの指定方法は次の2つです。
- 繰り返す範囲を数値(Int)で指定する方法【範囲指定】
- 一意性を持ったデータコレクションを渡す方法【データ指定】
本記事(1/2)では、1番目の方法について解説します。
2番目の方法については、【SwiftUI】ForEachの使い方(2/2)を参照して下さい。
環境
この記事の情報は次のバージョンで動作確認しています。
【iOS】16.4
【macOS】Ventura 13.5.2
基本的な使い方
1 2 3 4 5 6 7 8 9 10 11 |
struct ContentView: View { var body: some View { Form { ForEach(1..<6) { num in Text("\(num)行目") } } } } |
ForEachは複数のViewを生成しますので、FormやList、VStackなどのコンテナ内に記述するのが前提となります。また、Pickerの選択肢設定などにも使えます。
引数にはSwiftの範囲型(Range)で繰り返す範囲を指定します。上記の”1..<6”は1以上6未満(つまり1〜5)の範囲を指定しています。 ForEachは、繰り返すすべてのアイテム(この例では数値)に対して、{}で示すクロージャーを1回実行し、引数として現在のループアイテムを渡します。 引数名の指定は"引数名 in"と記述します。 1から5までループする場合は、1,2,3,4,5のように渡されます。
範囲指定で使う場合の注意点
このケースのForEachでは、イニシャライザに規定されている引数の型がRange
もう一つの注意点として、範囲を示す第一引数は初期読み込み時のみ考慮され、更新時の再描画には対応していません。そのため、リテラル値(固定値)以外を範囲指定に使用すると、次節で紹介する警告メッセージが表示されます。
配列(コレクション)での繰り返し処理
範囲型(Range)で繰り返す範囲を指定する方法を応用して、次のように配列(コレクション)を使った繰り返し処理が実現できます。
1 2 3 4 5 6 7 8 9 10 11 12 |
struct ContentView: View { let animals = ["カピバラ", "アルパカ", "トナカイ", "アルマジロ"] var body: some View { Form { ForEach(0..<animals.count) { num in Text(self.animals[num]) } } } } |
しかし、Xcode13.3以降で上記コードを実行すると、警告メッセージ"Non-constant range: argument must be an integer literal"が出るようになりました。
これは、animals.countが定数として処理される為、範囲に変動があった場合の再表示が行われず、想定外の問題が発生する可能性がある為です。
配列の繰り返し処理をしたい場合は【SwiftUI】ForEachの使い方(2/2)で解説するデータ指定の繰り返しを検討してみましょう。
それでも範囲指定にしたい場合は、次のように第二引数に"id: \.self"を追加すると、警告メッセージは消え、範囲に変動があった場合の再表示も行われるようになります。
一見、範囲指定になっていますが、内部的にはデータ指定の繰り返し処理として動いています。
1 2 3 |
ForEach(0..<animals.count, id: \.self) { num in |