如何自定义 SwiftUI ViewBuilder

Posted

技术标签:

【中文标题】如何自定义 SwiftUI ViewBuilder【英文标题】:How to customize the SwiftUI ViewBuilder 【发布时间】:2019-09-09 05:06:44 【问题描述】:

有一些关于 SwiftUI Builder 的帖子,例如 this。这样我就可以嵌入我的内容,例如:

struct Container<Content>: View where Content: View 

  var content: Content

  init(@ViewBuilder content: @escaping () -> Content) 
    self.content = content()
  

  var body: some View 
    return content
  


struct ContentView: View 
  var body: some View 
    Container() 
      Text("Content 1").tag(0)
      Text("Content 2").tag(1)
    
  

我想知道我是否没有在 init 中传递 ViewBuilder。相反,我想做类似的事情:

struct ContentView: View 
  var body: some View 
    Container().buildContent 
      Text("Content 1").tag(0)
      Text("Content 2").tag(1)
    
  

之所以要这样做,是因为我想模仿TabViewtabItem

【问题讨论】:

【参考方案1】:

您不能让buildContent 函数改变Container,但您可以默认拥有一个Container,它只是出售一个EmptyView,并将其用作创建新@987654325 的跳板@你想要的内容。

你可以像这样实现那种 API:

struct Container<Content>: View where Content: View 
    var content: Content

    init(@ViewBuilder content: () -> Content) 
        self.content = content()
    

    var body: some View 
        return content
    


extension Container where Content == EmptyView 
    init() 
        self.content = EmptyView()
    

    /// Return a new `Container` with the given `Content` builder.
    func buildContent<V : View>(@ViewBuilder content: () -> V) -> Container<V> 
        Container<V>(content: content)
    


struct ContentView: View 
    var body: some View 
        Container().buildContent 
            Text("Content 1").tag(0)
            Text("Content 2").tag(1)
        
    

【讨论】:

在您的示例中不需要@escaping,因为函数content 在构造函数结束之前就在那里被调用。如果您保存它并稍后调用它,您将需要它

以上是关于如何自定义 SwiftUI ViewBuilder的主要内容,如果未能解决你的问题,请参考以下文章

@ViewBuilder 在使用其他属性初始化时抛出错误

有啥方法可以在 SwiftUI 中使用 @ViewBuilder 创建/提取视图数组

@ViewBuilder 在自定义 View 中的使用

@ViewBuilder 在自定义 View 中的使用

@ViewBuilder 在自定义 View 中的使用

@ViewBuilder 在自定义 View 中的使用