在SwiftUI中,const_cast
将自动设置您传递它的子视图的格式,如下所示:
List
将导致两个文本视图正确放置,并在它们之间使用分隔符等。
此外,还可以混合使用静态和动态生成的数据,如下所示:
List {
Text("A")
Text("B")
}
我的目标是编写自己的自定义类型,以允许其用户进行这种使用(即:一种视图,该视图可让用户使用新的功能构建器DSL提供视图,而无需他们编写自己的修饰符来放置它们显示在屏幕上),但我根本不知道要在自定义视图的初始化程序中添加什么内容。
本机SwiftUI视图使用List {
Text("A")
ForEach(foo) { fooElement in CustomView(fooElement) }
Text("B")
ForEach(bar) { barElement in CustomView(barElement) }
}
并接收符合@ViewBuilder
的通用类型,但是它们能够提取元素(例如,从View
视图)是神秘的,我非常确定这是不可能的。
也许我错过了一些事情,所以很好奇您对此有何看法?
编辑:
一个例子可能更清楚。你们中的许多人肯定在网上看到了不错的示例,其中的卡片使用ForEach
并排放置,所以如果我想创建一个ZSack
类型的类型,该类型将允许我的用户编写这样的代码怎么办? ?
CardStack
这将导致12张卡片彼此堆叠,请注意,这些类型不是同质的,我们使用了CardStack {
SomeView()
AnotherView()
ForEach(1...10) { i in
NumberView(i)
}
}
。
答案 0 :(得分:0)
挑战的第一步是弄清楚ViewBuilder。关于从儿童到祖先的数据流,请继续阅读:
通过使用首选项(请参阅我的文章https://swiftui-lab.com/communicating-with-the-view-tree-part-1/),您可以使信息从孩子流向祖先。
一旦您完全理解了首选项并使它们生效,您可以尝试使实现更加清晰透明,这样您的Stack的最终用户甚至不会意识到自己正在使用首选项。为此,您可以使用一些View扩展。最终的代码可能如下所示:
CardStack {
SomeView().card(title: "", border: .red)
AnotherView().card(title: "", border: .green)
ForEach(items) { item in
NumberView(item).card(item.name, border: .blue)
}
}
您的.card()
实现可能是这样的:
extension View {
func card(title: String, border: Color) -> CardCustomizer<Self> {
return CardCustomizer(viewContent: self, title: title, border: border)
}
}
struct CardCustomizer<Content: View>: View {
public let viewContent: Content
public let title: String
public let border: Color
var body: some View {
viewContent.preference(MyCardPref.self, value: ...)
}
}
我认为最好是先尝试使它在没有View扩展的情况下工作,这样一来您就正确了。然后继续用扩展封装首选项逻辑。否则,有太多新事物要处理。