繁体   English   中英

如何将可选视图传递给 SwiftUI 中的另一个视图?

[英]How to pass optional view to another view in SwiftUI?

所以我有这个接受headerContentbodyContentTestView

struct TestView<Content: View>: View {
  let headerContent: (() -> Content)?  = nil
  let bodyContent: () -> Content
  
  var body: some View {
    VStack {
      headerContent?()
      bodyContent()
    }
  }
}

我用它作为,

struct ContentView: View {  
  var body: some View {
    TestView {
      Text("Body Content")
    }
  }
}

现在,我如何传递headerContent 我试着做,

struct ContentView: View {  
  var body: some View {
    TestView(headerContent: {
      Text("HeaderContent")
    }) {
      Text("BodyContent")
    }
  }
}

我得到错误,

Extra arguments at positions #1, #2 in call
Generic parameter 'Content' could not be inferred

将您的可选变量从let更改为var

当您使用let关键字定义变量时,您无法更改它。 在您的示例中,您已将 nil 设置为headerContent的常量。

struct TestView<Content: View>: View {
    var headerContent: (() -> Content)?  = nil
    let bodyContent: () -> Content

您也可以将letinit一起使用

struct TestView<Content: View>: View {
    let headerContent: (() -> Content)?
    let bodyContent: () -> Content
    
    init(headerContent: (() -> Content)?  = nil, bodyContent: @escaping () -> Content) {
        self.headerContent = headerContent
        self.bodyContent = bodyContent
    }

只需将其var (即可变)而不是let ,例如

struct TestView<Content: View>: View {
  var headerContent: (() -> Content)?  = nil     // << here !!

...

方式1:

这是一种方法,但如果您的 headerView 类型与正文内容不同,您会遇到问题和错误。 例如圆圈和文本:我以第二种方式解决了这个问题:

struct TestView<Content: View>: View {
    
    @ViewBuilder let headerContent: (() -> Content)?
    @ViewBuilder let bodyContent: () -> Content
    
    init(headerContent: (() -> Content)? = nil, bodyContent: @escaping () -> Content) {
        self.headerContent = headerContent
        self.bodyContent = bodyContent
    }
    
    var body: some View {
        
        return VStack {
            
            headerContent?()
            bodyContent()
        }
        
    }
    
}

方式2:

这是适合您的正确方法:

struct TestView<BodyContent: View, HeaderContent: View>: View {
    
    @ViewBuilder let headerContent: () -> HeaderContent
    @ViewBuilder let bodyContent: () -> BodyContent
    
    init(headerContent: @escaping () -> HeaderContent, bodyContent: @escaping () -> BodyContent) {
        self.headerContent = headerContent
        self.bodyContent = bodyContent
    }
    
    init(bodyContent: @escaping () -> BodyContent) where HeaderContent == EmptyView {
        self.headerContent = { EmptyView() }
        self.bodyContent = bodyContent
    }
    
    var body: some View {
        
      return VStack {
            
            headerContent()
            
            bodyContent()
        }
        
    }
}

用例:

struct ContentView: View {
    
    var body: some View {
          
        TestView(headerContent: {
            Circle().fill(Color.red).frame(width: 25, height: 25)
        }, bodyContent: {
            Text("Hello, World!")
        })
            

        TestView(bodyContent: {
            Text("Hello, World!")
        })

    }
    
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM