通用枚举菜单 SwiftUI

3
我正在尝试在SwiftUI中创建一个类似下面代码的菜单视图的View结构体。但是我遇到了一个错误,"Failed to produce diagnostic for expression; please submit a bug report"。我不知道我做错了什么。
明确一下,我想创建一个结构体,可以输入一个枚举,一个文本字符串和一个按钮操作,并返回一个菜单,以使contentView更易读。
希望你们能帮助我。干杯。
struct AddObjectMenuView<T: RawRepresentable, CaseIterable>: View {
    
    let labelText: String
    let someEnum: T
    let function: () -> Void
    
    var body: some View { // Getting error here
        Menu {
            ForEach(someEnum.allCases) { field in
                Button(action: function) {
                    VStack {
                        Text(field.rawValue).padding()
                    }
                }
            }
        } label: {
            Text(labelText).padding().background(RoundedRectangle(cornerRadius: 10).foregroundColor(.clear))
        }
        .foregroundColor(Color("lightBlue"))
    }
    
}

然后在我的ContentView中像这样使用它:

        AddObjectMenuView(labelText: "Hello", someEnum: SomeEnum, function: {
            // Do something
        })

尝试 struct AddObjectMenuView<T: RawRepresentable, CaseIterable>: View where T.RawValue == String { - Leo Dabus
@LeoDabus 很不幸,结果一样...同样的错误。 - patturik
你遇到了什么错误? - Leo Dabus
生成表达式诊断失败,请提交错误报告。 - patturik
1个回答

3

你需要使用泛型类型来使用.allCases

以下是修改后的版本(已用内联方式突出显示修改的部分)。已在Xcode 13.2 / iOS 15.2上测试通过。

struct AddObjectMenuView<T: CaseIterable & Hashable> : View where T.AllCases: RandomAccessCollection {

    let labelText: String
    let someEnum: T.Type     // << here !!
    let function: () -> Void

    var body: some View {
        Menu {
            ForEach(someEnum.allCases, id: \.self) { field in   // << here !!
                Button(action: function) {
                    VStack {
                        Text(String(describing: field)).padding()  // << here !!
                    }
                }
            }
        } label: {
            Text(labelText).padding().background(RoundedRectangle(cornerRadius: 10).foregroundColor(.clear))
        }
        .foregroundColor(Color("lightBlue"))
    }
}

当然,枚举应该相应地进行确认。

像这样的用法:

AddObjectMenuView(labelText: "Hello", someEnum: SomeEnum.self, function: {
    // Do something
})

2
我会添加另一个限制条件 T.RawValue == String,所以 struct AddObjectMenuView<T: RawRepresentable & CaseIterable & Hashable> : View where T.AllCases: RandomAccessCollection, T.RawValue == String 并且你可以使用 Text(field.rawValue)。当然,您的方法更通用,但我认为 OP 不需要除字符串之外的任何内容。 - Leo Dabus
1
@Asperi 太棒了!这个可行。而且 @Leo Dabus 我也加入了你的建议,并添加了 Identifiable 以符合要求,所以你不需要 id: \.self - patturik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接