Container values pass data from a child view up to its custom container, the way environment
values pass data down. The container reads them off each Subview or SectionConfiguration
and changes its layout, so callers tag content instead of relying on positional order.
Define a value with @Entry
Extend ContainerValues with the @Entry macro and a default. Set it on any view or section
with containerValue(_:_:), and wrap that in a View extension for a cleaner call site.
extension ContainerValues {
@Entry var isFeatured = false
}
extension View {
func featured(_ isFeatured: Bool = true) -> some View {
containerValue(\.isFeatured, isFeatured)
}
}
Tag content at the call site
Magazine {
Section(header: Text("Favorites")) {
Color.red
Color.orange
}
Section {
Color.green
Color.yellow
}
.featured()
}
Without container values the container must hard-code positions, for example "the first section is prominent". The tag makes the choice explicit and order-independent.
Read values inside the container
Both Subview and SectionConfiguration expose containerValues. Filter on the value to
recompose the hierarchy.
Group(sections: content) { sections in
let featured = sections.filter(\.containerValues.isFeatured)
ForEach(featured) { section in
section.content.frame(minHeight: 100)
}
let rest = sections.filter { !$0.containerValues.isFeatured }
ForEach(rest) { section in
section.header
// horizontal rail per section
section.footer
}
}
Container values propagate like environment values: every view inside a featured section reads
isFeatured as true.