如何让Swift的Alignment类型遵循Hashable协议?
让Alignment遵循Hashable以用于SwiftUI Picker
方法一:直接扩展Alignment实现Hashable
Alignment结构体本身包含horizontal(HorizontalAlignment类型)和vertical(VerticalAlignment类型)两个核心属性,而这两个类型默认已经遵循Hashable协议。我们可以基于这两个属性实现Hashable的要求:
extension Alignment: Hashable { public static func == (lhs: Alignment, rhs: Alignment) -> Bool { lhs.horizontal == rhs.horizontal && lhs.vertical == rhs.vertical } public func hash(into hasher: inout Hasher) { hasher.combine(horizontal) hasher.combine(vertical) } }
添加这个扩展后,你的原代码就能正常编译,Picker可以直接绑定Alignment类型的@State变量。
方法二:使用自定义枚举映射Alignment(更可控)
如果你的Picker只需要展示预设的常用对齐选项,推荐用这种方式——自定义一个遵循Hashable的枚举,对应常用的Alignment值,再提供转成Alignment的计算属性:
// 定义包含常用对齐方式的枚举 enum AlignmentOption: Hashable, CaseIterable { case topLeading, top, topTrailing case leading, center, trailing case bottomLeading, bottom, bottomTrailing // 映射到对应的Alignment var alignment: Alignment { switch self { case .topLeading: return .topLeading case .top: return .top case .topTrailing: return .topTrailing case .leading: return .leading case .center: return .center case .trailing: return .trailing case .bottomLeading: return .bottomLeading case .bottom: return .bottom case .bottomTrailing: return .bottomTrailing } } } // 使用示例 struct ContentView: View { @State private var favouriteCorner: AlignmentOption = .center var body: some View { Picker("Select favourite corner", selection: $favouriteCorner) { ForEach(AlignmentOption.allCases, id: \.self) { option in Text(String(describing: option)).tag(option) } } // 使用对齐方式时,通过alignment属性获取 .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color.gray.opacity(0.2)) .background(Color.red.frame(width: 50, height: 50), alignment: favouriteCorner.alignment) } }
这种方法能严格限制Picker的可选范围,避免出现自定义的、不符合预期的Alignment值,代码逻辑也更清晰。
内容的提问来源于stack exchange,提问作者Per Lindgren
相关产品推荐
相关产品推荐

