550просмотров
11 ноября 2025 г.
questionScore: 605
Что ещё можно сделать, чтобы улучшить это решение? В большинстве ресурсов и даже в документации Apple, можно найти примеры в духе: @resultBuilder
struct ExampleResultBuilder { // ... static func buildBlock(_ components: Component...) -> Component { ... } Они, к сожалению, не подскажут верное решение. Но если заглянуть в исходники SwiftUI, то можно заметить, что ViewBuilder выглядит по-другому: @resultBuilder struct ViewBuilder { // ... static func buildBlock<each Content: View>( _ content: repeat each Content ) -> TupleView<(repeat each Content)>
} Для работы со статическим списком View он использует pack iteration. И это как раз то, что нам нужно: @MainActor
@resultBuilder
struct ButtonsListBuilder { static func buildBlock<each Content: ButtonModelProtocol>( _ content: repeat each Content, ) -> TupleView<(repeat ButtonBody<each Content>)> { TupleView((repeat ButtonBody(model: each content))) }
} // Pack Iteration only works with protocols.
protocol ButtonModelProtocol { ... } struct ButtonBody<Model: ButtonModelProtocol>: View { let model: Model public var body: some View { Button { ... } }
} struct ButtonsList<Buttons: View>: View { @ButtonsListBuilder let buttons: Buttons var body: some View { VStack { buttons } }
} #Preview { ButtonsList { ButtonModel(title: "First Button", action: {}) ButtonModel(title: "Second Button", action: {}) }
} С таким подходом пропадает необходимость использовать не только ForEach, но и массивы в принципе. Это значит, что код будет работать максимально эффективно, предоставляя при этом удобный API для использования. Кстати, в канале есть отдельный пост про pack iteration, где можно узнать ещё больше деталей о том, как эта фича работает.