声明内容符合 View 协议的结构数组

Posted

技术标签:

【中文标题】声明内容符合 View 协议的结构数组【英文标题】:Declare an array of structs whose content conforms to View protocol 【发布时间】:2021-04-05 09:52:30 【问题描述】:

前缀:我是 Swift 中泛型的新手。这就是为什么我很难理解以下问题和生成的编译器消息的原因。

使用 SwiftUI,我创建了一个结构 'AlignedForm',它应该使用一个数组来保存多个 'AlignedFormRow' 结构。这些 AlignedFormRows 由右侧的文本标签和左侧的任意视图组成。它们被实现为这样的泛型类型:

struct AlignedFormRow<Content>: View where Content: View 
    let content: Content
    let title: String
    let titleWidth: CGFloat

    init(_ title: String, titleWidth: CGFloat, @ViewBuilder content: @escaping () -> Content) 
        self.title = title
        self.titleWidth = titleWidth
        self.content = content()
    

    var body: some View 
        HStack 
            Text(title).frame(width: titleWidth, alignment: .trailing)
            content
        
    

现在,我可以像这样以漂亮的 SwiftUI 风格为我的表单行创建内容:

VStack 
    AlignedFormRow("Full Name", titleWidth:100.0) 
        TextField("your name", text: $name)
    
    AlignedFormRow("Email", titleWidth:100.0) 
        TextField("your email", text: $email)
    

这会产生两个对齐的标签文本字段:

到目前为止,它工作正常。现在,我想创建一个辅助结构“AlignedForm”来管理所有行的 titleWidth。但是当我尝试实现 AlignedForm 时,我遇到了声明“行”数组的问题:

struct AlignedForm 
    let rows: [AlignedFormRow<Content: View>]

代码无法编译,编译器以“预期'>' 来完成通用参数列表”响应该行,这对我来说没有多大意义。我盲目地尝试了许多不同的方法来声明这个行数组,但它永远不会编译。这里的正确语法是什么?还是这种方法有其他缺陷?

【问题讨论】:

泛型不是这样工作的。您需要使用具体类型,如AlignedFormRow&lt;MyView&gt;,或在body 中按行数据(如ForEach 有效)就地创建这些实例。第二种方式更可取。 所以,你的意思是不可能声明像 Array> 这样的数组? 【参考方案1】:

我不知道你为什么写AlignedFormRow&lt;Content: View&gt;。 首先,您需要创建一个符合 View 协议的结构,然后在声明中使用它。喜欢,

struct AlignedFormView: View 
    var body: some View 
        EmptyView()
    

然后,在你的数组中使用它。

struct AlignedForm 
    let rows: [AlignedFormRow<AlignedFormView>]

就是这样。谢谢

【讨论】:

因为我尝试通过使用@ViewBuilder 来实现 SwiftUI 风格(我编辑了我的帖子以展示如何创建 AlignedFormRows)。这就是 AlignedFormRow 泛型的原因。 当你想返回多个视图时,你需要使用@ViewBuilder。在您的代码中,您想要声明一个 AlignedFormRow 数组。但是,你没有提供。你刚才说的是。在创建 where Content: View 时,您已经这样做了。所以,问题是,假设你做了一个袋子并贴上标签来装茶叶。现在你想制作一个容器并在里面放几个袋子。现在,你不能只把空袋子放在容器里,因为那里没有叶子,然后再贴上标签来装茶叶。你一开始就已经这样做了。 现在,您需要将茶叶放入袋中,然后将袋子放入容器中。就像这样,您需要创建一个视图并使用它创建 AlignedFormRow,然后将它们放入数组中。 谢谢,这个类比帮助了我。我的印象是我可以声明一组“不同种类茶叶的相同袋子”,但这可能仍然是一个异构数组。

以上是关于声明内容符合 View 协议的结构数组的主要内容,如果未能解决你的问题,请参考以下文章

使用 if 语句时:类型 '()' 不能符合 'View';只有结构/枚举/类类型可以符合协议

type() 不能符合 View;只有结构/枚举/类类型可以符合协议

“类型‘()’不能符合‘视图’;只有结构/枚举/类类型可以符合协议”

使用 JSONEncoder 编码/解码符合协议的类型数组

Swift 5:在使用协议实现 Equatable 的结构上实现通用数组操作

使协议可编码并将其存储在数组中