Skip to content

Instantly share code, notes, and snippets.

@chriseidhof
Last active March 27, 2024 19:14
Show Gist options
  • Save chriseidhof/5ff6ef8786f5635c18b20304ab9d9b01 to your computer and use it in GitHub Desktop.
Save chriseidhof/5ff6ef8786f5635c18b20304ab9d9b01 to your computer and use it in GitHub Desktop.
Variadic Views
import SwiftUI
struct MyValue: _ViewTraitKey {
static var defaultValue: Int = 0
}
extension View {
func myValue(_ value: Int) -> some View {
_trait(MyValue.self, value)
}
}
struct ContentView: View {
var subviews: some View {
ForEach(0..<5) { ix in
Text("Hello \(ix)")
.myValue(ix)
}
}
var body: some View {
VStack {
VStack {
subviews.intersperse(Divider())
}
HStack {
subviews.reduce { v1, v2 in
// Render the views backwards with dividers in between
v2
Divider()
v1
}
}
HStack {
subviews.filter { $0[MyValue.self].isMultiple(of: 2) }
}
.padding()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
import Foundation
import SwiftUI
extension View {
func filter(_ condition: @escaping (_VariadicView.Children.Element) -> Bool) -> some View {
variadic { children in
ForEach(children) { child in
if condition(child) {
child
}
}
}
}
}
import Foundation
import SwiftUI
extension View {
func intersperse<V: View>(_ divider: V) -> some View {
variadic { children in
if let c = children.first {
c
ForEach(children.dropFirst(1)) { child in
divider
child
}
}
}
}
}
import SwiftUI
extension View {
func reduce<R: View>(@ViewBuilder _ combine: @escaping (AnyView, AnyView) -> R) -> some View {
variadic { children in
if let c = children.first {
children.dropFirst(1).reduce(AnyView(c), { l, r in
AnyView(combine(l, AnyView(r)))
})
}
}
}
}
import SwiftUI
extension View {
func variadic<R: View>(@ViewBuilder process: @escaping (_VariadicView.Children) -> R) -> some View {
modifier(VariadicModifier(helper: Helper(process: process)))
}
}
fileprivate struct VariadicModifier<R: View>: ViewModifier {
var helper: Helper<R>
func body(content: Content) -> some View {
_VariadicView.Tree(helper) {
content
}
}
}
fileprivate struct Helper<Result: View>: _VariadicView_MultiViewRoot {
var process: (_VariadicView.Children) -> Result
func body(children: _VariadicView.Children) -> some View {
process(children)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment