我在项目中定义了以下容器,第一个容器可以工作,但是第二个容器不能,因为它会引发以下错误。
参数类型“ForEach
,Range .Element,PageX>”(又名“ForEach ”)不符合预期类型“PageXItem”
@PageBuilder
在我的NavX
结构上实现,如下所示。
@PageBuilder private var content: () -> Content
我希望能够使用独立的
PageX
或通过使用 ForEach
来使用动态集合。无论它是 ForEach(array.indices)
还是任何序列都没关系,这样 ForEach
的每个元素都保证是 PageX
。
NavX {
PageX {
}
}
或
NavX {
ForEach(...) { _ in
PageX {...}
}
}
这是目前使用的
@PageBuilder
。最后两个是我最近为实现此目的所做的尝试,但没有一个被证明是成功的。
@resultBuilder
public struct PageBuilder {
/// Builds a collection of `PageXItem` views.
///
/// - Parameter components: A variadic list of views conforming to `PageXItem`.
/// - Returns: An array of views that conform to `PageXItem`.
static public func buildBlock(_ components: any PageXItem...) -> [any PageXItem] {
components
}
/// Builds a collection of `PageXItem` views, particularly useful for conditional view constructions.
///
/// - Parameter components: A variadic list of arrays of views conforming to `PageXItem`.
/// - Returns: An array of views that conform to `PageXItem`.
static public func buildPartialBlock(_ components: [any PageXItem]...) -> [any PageXItem] {
components.flatMap { $0 }
}
static public func buildFinalResult(_ component: [any PageXItem]) -> [any PageXItem] {
component
}
static public func buildBlock<C: View>(_ component: ForEach<[any PageXItem], UUID, C>) -> ForEach<[any PageXItem], UUID, C> {
component
}
}
要与
ForEach
合作,您应遵守以下要求:
View
(如果不符合),因为 ForEach
仅适用于视图。struct Item {
let name: String
}
extension Item: View {
public var body: Never {
fatalError()
}
}
@resultBuilder
必须仅使用专用协议运行。protocol ItemConvertible {
var items: [Item] { get }
}
extension Item: ItemConvertible {
var items: [Item] {
[self]
}
}
@resultBuilder
struct ItemsBuilder {
static func buildBlock(_ components: ItemConvertible...) -> [ItemConvertible] {
components
}
static func buildFinalResult(_ components: [ItemConvertible]) -> [Item] {
components.flatMap(\.items)
}
}
ForEach
。extension ForEach: ItemConvertible where Content == Item {
var items: [Item] {
data.map(content)
}
}
现在您可以编写构建器函数了:
@ItemsBuilder
func content() -> [Item] {
Item(name: "1")
Item(name: "2")
ForEach(3..<5) {
Item(name: "\($0)")
}
}
print(content()) // [Item(name: "1"), Item(name: "2"), Item(name: "3"), Item(name: "4")]