SwiftUIにはVStackやHStackなどのコンテナでViewを10個までしか並べられない制限があります。
11個以上のViewを並べる方法を紹介します。
環境
この記事の情報は次のバージョンで動作確認しています。
【Xcode】11.2.1
【Swift】5.1
【iOS】13.2.2
【macOS】Catalina バージョン 10.15.2
【Swift】5.1
【iOS】13.2.2
【macOS】Catalina バージョン 10.15.2
SwiftUIの制限
次のコードはText Viewを11個縦に並べるだけのものですが、SwiftUIでは一見意味不明のコンパイルエラー(Argument passed to call that takes no arguments)になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
struct ContentView: View { var body: some View { VStack { Text("1行目") Text("2行目") Text("3行目") Text("4行目") Text("5行目") Text("6行目") Text("7行目") Text("8行目") Text("9行目") Text("10行目") Text("11行目") } } } |
VStackのイニシャライザを見ると次のように規定されています。
1 2 3 |
init(alignment: HorizontalAlignment = .center, spacing: CGFloat? = nil, @ViewBuilder content: () -> Content) |
3つめの引数contentが実際に並べるViewを指定する部分ですが、この引数にSwiftUIのカスタム属性である@ViewBuilderが付いているのがポイントです。
実はこの@ViewBuilder属性に、指定できるViewの数が10個までの制限があります。
@ViewBuilderはVStack、HStack、Formなどのコンテナの他、Button、Pickerなどの多くの標準部品にも使われており、その全てにこの制限が適用されます。
この制限を回避する方法を次節以降で紹介します。
GroupでViewをグループ化する
GroupでいくつかのViewを1つのViewにまとめる事で、コンテナに渡すViewの数を減らす事ができます。
Groupは入れ子にする事も可能なので、実質的に数の制限は無くなります。
次の例は、最後の3行を1つにまとめている為、VStackに渡されるViewの数は9個となり、制限内に収まっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
struct ContentView: View { var body: some View { VStack { Text("1行目") Text("2行目") Text("3行目") Text("4行目") Text("5行目") Text("6行目") Text("7行目") Text("8行目") Group { // 以下3行を1つのViewにまとめる Text("9行目") Text("10行目") Text("11行目") } } } } |
ForEachを使った方法
ForEachは繰り返し処理の中で、Viewを追加する仕組みです。
次のように使い、先の例と同様の結果を得られます。
1 2 3 4 5 6 7 8 9 10 11 |
struct ContentView: View { var body: some View { VStack { ForEach(1 ..< 12) { count in // 1から11まで繰り返す Text("\(count)行目") } } } } |
ForEachの詳しい使い方は次の記事を参照して下さい。
【SwiftUI】ForEachの使い方(1/2)
(2023/09/18 更新) ForEachは繰り返し処理の中で、Viewを生成する仕組みです。文字列の入った配列をループしてそれぞれをTextViewに変換する、またはメニュー項目に追加するような動きを実現します。さらに、ForEach...