Skip to content

Instantly share code, notes, and snippets.

@shaps80
Last active October 23, 2024 20:01
Show Gist options
  • Save shaps80/d192991d5abab8484c92e824de0d9abf to your computer and use it in GitHub Desktop.
Save shaps80/d192991d5abab8484c92e824de0d9abf to your computer and use it in GitHub Desktop.
import SwiftUI
extension Backport<Any> {
@MainActor
public struct Group<Content: View>: View, Sendable {
private var content: Content
public init<Base, Result>(
subviewsOf view: Base,
@ViewBuilder transform: @escaping (SubviewsCollection) -> Result
) where Content == GroupElementsOfContent<Base, Result>, Base: View, Result: View {
content = GroupElementsOfContent(view, subviews: transform)
}
public var body: some View {
content
}
}
@MainActor
public struct GroupElementsOfContent<Subviews, Content>: View, Sendable where Subviews: View, Content: View {
private var content: AnyView
init<Source: View>(_ source: Source, @ViewBuilder subviews: @escaping (SubviewsCollection) -> Content) {
self.content = .init(source.variadic { subviews(SubviewsCollection(children: $0)) })
}
public var body: some View {
content
}
}
}
@MainActor
public struct Subview: View, @preconcurrency Identifiable, Sendable {
public struct ID: Hashable {
fileprivate let wrapped: AnyHashable
}
public let id: ID
private let content: _VariadicView.Children.Element
internal init(_ content: _VariadicView.Children.Element) {
self.id = .init(wrapped: content.id)
self.content = content
}
public var body: some View {
content
}
}
@MainActor
public struct SubviewsCollection: RandomAccessCollection, View, Sendable {
public typealias SubSequence = SubviewsCollectionSlice
public typealias Iterator = IndexingIterator<SubviewsCollection>
public typealias Indices = Range<Int>
public typealias Index = Int
public typealias Element = Subview
nonisolated public var startIndex: Int {
MainActor.assumeIsolated { children.startIndex }
}
nonisolated public var endIndex: Int {
MainActor.assumeIsolated { children.endIndex }
}
nonisolated public func index(before i: Int) -> Int {
MainActor.assumeIsolated { children.index(before: i) }
}
nonisolated public func index(after i: Int) -> Int {
MainActor.assumeIsolated { children.index(after: i) }
}
nonisolated public subscript(position: Int) -> Subview {
MainActor.assumeIsolated { .init(children[position]) }
}
nonisolated public subscript(bounds: Range<Int>) -> SubviewsCollectionSlice {
MainActor.assumeIsolated { .init(children: children[bounds]) }
}
fileprivate let children: _VariadicView.Children
public var body: some View {
ForEach(children, id: \.id) { $0.id($0.id) }
}
}
@MainActor
public struct SubviewsCollectionSlice: RandomAccessCollection, View, Sendable {
public typealias SubSequence = SubviewsCollectionSlice
public typealias Element = Subview
public typealias Iterator = IndexingIterator<SubviewsCollectionSlice>
public typealias Indices = Range<Int>
public typealias Index = Int
nonisolated public var startIndex: Int {
MainActor.assumeIsolated { children.startIndex }
}
nonisolated public var endIndex: Int {
MainActor.assumeIsolated { children.endIndex }
}
nonisolated public subscript(position: Int) -> Subview {
MainActor.assumeIsolated { .init(children[position]) }
}
nonisolated public subscript(bounds: Range<Int>) -> SubviewsCollectionSlice {
MainActor.assumeIsolated { .init(children: children[bounds]) }
}
fileprivate let children: _VariadicView.Children.SubSequence
public var body: some View {
ForEach(children, id: \.id) { $0 }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment