Swiftui 从枚举创建列表
我希望能够从符合CaseIterable和CustomStringConverable的枚举创建一个列表,例如 公共枚举头发颜色:Int、可编码、可大小写、可自定义{ 公共变量说明:字符串{ 切换自身{ 黑色: 返回黑色 案例:金发碧眼: 金发碧眼 布朗先生: 返回棕色 红色: 返回红色 案例.灰色: 返回灰色 案例.秃头: 光头 } } 案例金发、棕色、黑色、红色、灰色、秃顶 } 结构ContentView:View{ var body:一些观点{ SwiftUIHelpers.enumToListHairColor } } 这是我尝试过的方法,但我得到了错误:无法将“Text”类型的值转换为“closure result type”_ 结构快捷助手{ 静态函数枚举列表\ua:T->某些视图{ 名单{ ForEacha,id:\.rawValue{o:CustomStringConvertible in 文字说明 } } } }Swiftui 从枚举创建列表,swiftui,Swiftui,我希望能够从符合CaseIterable和CustomStringConverable的枚举创建一个列表,例如 公共枚举头发颜色:Int、可编码、可大小写、可自定义{ 公共变量说明:字符串{ 切换自身{ 黑色: 返回黑色 案例:金发碧眼: 金发碧眼 布朗先生: 返回棕色 红色: 返回红色 案例.灰色: 返回灰色 案例.秃头: 光头 } } 案例金发、棕色、黑色、红色、灰色、秃顶 } 结构ContentView:View{ var body:一些观点{ SwiftUIHelpers.enumToL
我的方法有什么错误 这是有效的解决方案。使用Xcode 11.4/iOS 13.4进行测试
struct SwiftUIHelpers {
static func enumToList<T: CaseIterable>(_ t: T.Type) -> some View
where T.AllCases: RandomAccessCollection, T: Hashable & CustomStringConvertible {
List {
ForEach(t.self.allCases, id: \.self) { o in
Text(o.description)
}
}
}
}
struct ContentView: View {
var body: some View {
SwiftUIHelpers.enumToList(HairColor.self)
}
}
public enum HairColor: Int, Codable, Hashable, CaseIterable, CustomStringConvertible {
public var description: String {
switch self {
case .black:
return "Black"
case .blond:
return "Blond"
case .brown:
return "Brown"
case .red:
return "Red"
case .grey:
return "Gray"
case .bald:
return "Bald"
}
}
case blond, brown, black, red, grey, bald
}
因为它提供了更广泛的重用可能性,比如
List { HairColor.toForEach() }
还有这个
Form { HairColor.toForEach() }
及
当然,在任何堆栈中,VStack{HairColor.toForEach}并不是对你问题的所有部分的真正回答——只是第一部分——而是作为一种替代方案提供的 是否值得考虑将@EnvironmentObject用于@Published属性?我用它来填充macOS目标的边栏式菜单 步骤1: 使用您的枚举。我的枚举与你的枚举写得有点不同,但我想不写了,因为它提供了一种替代结构。。。但结果是一样的 符合CaseIterable允许我们在步骤2中使用.allCases方法
enum HairColor: Int, CaseIterable {
case blond = 0, brown, black, red, grey, none
var description: String {
switch self {
case .blond: return "Blond"
case .brown: return "Brown"
case .black: return "Black"
case .red: return "Red"
case .grey: return "Grey"
case .none: return "Bald"
}
}
}
步骤2:
为模型创建一个结构,并包含一个静态属性,该属性映射HairColor枚举的所有实例
符合此处的可识别性允许我们在步骤4中使用更干净的ForEach语法,即使用ForEachappData.hairolors代替ForEachappData.hairolors,id:\.id
步骤3:
创建一个符合ObserveObject的类,该类包含@Published wrapped属性,允许您通过@EnvironmentObject广播头发颜色
import Combine // <- don't forget this framework import!
import SwiftUI
final class AppData: ObservableObject {
@Published var hairColors = Hair.colors
}
步骤5:
请记住将环境对象注入预览以使预览可用
struct HairList_Previews: PreviewProvider {
static var previews: some View {
HairList(selectedHair: .constant(AppData().hairColors[1]))
.environmentObject(AppData())
}
}
这肯定是越来越近了,谢谢!列表无法用ForEacht.self.allCases标识元素,id:\.self,您知道如何让ForEacht.self.allCases,id:\.rawValue编译吗?@Norman,如前所述,answer中提供的代码在运行时编译和测试。首先,谢谢你在这方面的帮助。虽然您提供的解决方案可以正确编译甚至显示,但由于使用了id:\.self,它没有为列表提供区分每个元素的机制。当您实际使用您建议的代码时,例如在表单选择器中,由于此问题,所选项目未注册。要有一个功能列表,其中的每个元素都是可识别的,因此需要使用id:\.rawValue。我已经在上发布了代码,以演示建议解决方案的问题。请注意,在使用更新的扩展名时,选择器不会保留所选的值。感谢您提供了如此周到且文档完整的解决方案!虽然它不能解决我目前的困境,但它让我思考了很多问题,例如,将枚举案例包装在一个可识别的包装器中,并向我介绍了SidebarListStyle,如果做一些Mac工作,我会将其归档。再次感谢您,您的回答非常清楚。
import SwiftUI
struct Hair: Codable, Hashable, Identifiable {
var id: Int
var name: String
init(id: Int, name: String) {
self.id = id
self.name = name
}
static var colors: [Hair] {
return HairColor.allCases.map({ Hair(id: $0.rawValue, name: $0.description ) })
}
}
import Combine // <- don't forget this framework import!
import SwiftUI
final class AppData: ObservableObject {
@Published var hairColors = Hair.colors
}
struct HairList: View {
@EnvironmentObject var appData: AppData
@State var selectedHair: Hair?
var body: some View {
VStack(alignment: .leading) {
Text("Select...")
.font(.headline)
List(selection: $selectedHair) {
ForEach(appData.hairColors) { hairColor in
Text(hairColor.name).tag(hairColor)
}
}
.listStyle(SidebarListStyle())
}
.frame(minWidth: 100, maxWidth: 150)
.padding()
}
}
struct HairList_Previews: PreviewProvider {
static var previews: some View {
HairList(selectedHair: .constant(AppData().hairColors[1]))
.environmentObject(AppData())
}
}