SwiftUI自定义泛型组件报错:无法将[ASValue<T>]转为Binding<C>
解决SwiftUI中自定义泛型类型结合ForEach的类型转换错误
你遇到的错误源于编译器对ForEach重载的歧义判断,同时代码中存在多处类型不匹配问题,导致无法正确推断参数类型。以下是具体修复方案:
修复步骤
1. 明确ForEach的唯一标识
将ASValue中的私有id改为public,直接用该UUID作为ForEach的唯一标识,避免Hashable协议带来的重载混淆:
public struct ASValue<T: Hashable>: Hashable { public let id = UUID() // 修改为public var item: T public init(item: T) { self.item = item } }
之后在ForEach中指定id: \.id:
ForEach(section.items, id: \.id) { item in // 内容 }
2. 修正类型不匹配问题
代码中有3处类型不匹配的地方,需逐一调整:
Text(display(item))→Text(display(item.item)):display需要T类型参数,需取出ASValue<T>内部的item属性values.selected.item = item→values.selected = item:selected是ASValue<T>类型,直接赋值整个实例即可if values.selected.item == item→if values.selected == item:直接比较两个ASValue<T>实例(已实现Hashable协议)
修改后的完整代码
public struct ArrayStepperSection<T: Hashable>: Hashable { public let header: String public var items: [ASValue<T>] public init(header: String = "", items: [ASValue<T>]) { self.header = header self.items = items } } public struct ASValue<T: Hashable>: Hashable { public let id = UUID() var item: T public init(item: T) { self.item = item } } public class ArrayStepperValues<T: Hashable>: Hashable, ObservableObject { @Published public var values: [ASValue<T>] @Published public var selected: ASValue<T> @Published public var sections: [ArrayStepperSection<T>] public init(values: [ASValue<T>], selected: ASValue<T>, sections: [ArrayStepperSection<T>]? = nil) { self.values = values self.selected = selected self.sections = sections ?? [ArrayStepperSection(items: values)] // 简化可选绑定逻辑 } public static func == (lhs: ArrayStepperValues<T>, rhs: ArrayStepperValues<T>) -> Bool { return lhs.sections == rhs.sections } public func hash(into hasher: inout Hasher) { hasher.combine(sections) } } struct ArrayStepperList<T: Hashable>: View { @Environment(\.dismiss) var dismiss @ObservedObject var values: ArrayStepperValues<T> let display: (T) -> String var body: some View { List { ForEach(values.sections, id: \.self) { section in Section(section.header) { ForEach(section.items, id: \.id) { item in Button(action: { values.selected = item dismiss() }) { HStack { Text(display(item.item)) Spacer() if values.selected == item { Image(systemName: "checkmark") } } } } } } } .listStyle(InsetGroupedListStyle()) .navigationTitle(Text(display(values.selected.item))) } }
内容的提问来源于stack exchange,提问作者Joe Scotto
相关产品推荐
相关产品推荐

