SwiftUI: равномерное распределение нескольких VStack в VStack с помощью разделителей

Я пытаюсь создать VStack (контейнер), содержащий несколько VStack (элемент) с заголовком и текстом. Элементы VStacks должны быть распределены поровну и иметь промежуточную прокладку.

По какой-то причине он работает только до 4-х элементных VStack, и если я увеличу, то получу ошибку

Failed to build ContentView.swift
Ambiguous reference to member 'buildingBlock()'

Вот мой код:

import SwiftUI

struct ContentView: View {
    var body: some View {

        VStack {
            Spacer()
            VStack {
                Text("Title 1")
                Text("Text 1")
            }
            Spacer()
            VStack {
                Text("Title 2")
                Text("Text 2")
            }
            Spacer()
            VStack {
                Text("Title 3")
                Text("Text 3")
            }
            Spacer()
            VStack {
                Text("Title 4")
                Text("Text 4")
            }
            Spacer()
            VStack {
                Text("Title 5")
                Text("Text 5")
            }
            Spacer()
            VStack {
                Text("Title 6")
                Text("Text 6")
            }
            Spacer()
            VStack {
                Text("Title 7")
                Text("Text 7")
            }
            Spacer()
            VStack {
                Text("Title 8")
                Text("Text 8")
            }
            Spacer()
            VStack {
                Text("Title 9")
                Text("Text 9")
            }
            Spacer()
            VStack {
                Text("Title 10")
                Text("Text 10")
            }
            Spacer()'
        }
        .background(Color.red)

    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

1 ответ

Решение

Из-за способа реализации SwiftUI представление может иметь не более 10 прямых явных подвидов. Ваш высший уровеньVStack имеет 21 прямую подписку: 10 детей VStacks, а 11 Spacerвокруг них.

Существуют различные обходные пути. Если вам действительно нужен жестко запрограммированный список подвидов, вы можете использоватьGroup сделать некоторых детей косвенными:

struct ContentView: View {
    var body: some View {

        VStack {
            Group {
                Spacer()
                VStack {
                    Text("Title 1")
                    Text("Text 1")
                }
                Spacer()
                VStack {
                    Text("Title 2")
                    Text("Text 2")
                }
                Spacer()
                VStack {
                    Text("Title 3")
                    Text("Text 3")
                }
            }
            Group {
                Spacer()
                VStack {
                    Text("Title 4")
                    Text("Text 4")
                }
                Spacer()
                VStack {
                    Text("Title 5")
                    Text("Text 5")
                }
                Spacer()
                VStack {
                    Text("Title 6")
                    Text("Text 6")
                }
            }
            Group {
                Spacer()
                VStack {
                    Text("Title 7")
                    Text("Text 7")
                }
                Spacer()
                VStack {
                    Text("Title 8")
                    Text("Text 8")
                }
                Spacer()
                VStack {
                    Text("Title 9")
                    Text("Text 9")
                }
            }
            Spacer()
            VStack {
                Text("Title 10")
                Text("Text 10")
            }
            Spacer()
        }
        .background(Color.red)
    }
}

Здесь верхний уровень VStack имеет 6 прямых детей: 3 Group, 2 Spacer, и 1 VStack. КаждыйGroup также имеет 6 прямых детей: 3 VStack и 3 Spacer. Ни у одного представления не более 10 прямых детей.

Здесь лучше использовать ForEach для создания детей:

struct ContentView: View {
    var body: some View {

        VStack {
            Spacer()
            ForEach(1 ... 10, id: \.self) { i in
                Group {
                    VStack {
                        Text("Title \(i)")
                        Text("Text \(i)")
                    }
                    Spacer()
                }
            }
        }
        .background(Color.red)
    }
}

Теперь на высшем уровне VStack есть только два прямых подвида: первое Spacer и ForEach. ВForEach копирует свое подвид (Group) столько раз, сколько необходимо.

Мы используем Group в этом случае, чтобы Swift мог определить тип ForEach тело, так как ForEach в противном случае тело содержало бы два оператора (VStack и Spacer), что помешало бы Swift определить его тип.

Другие вопросы по тегам