You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中ForEach遍历AnyShape数组报Hashable兼容错误,如何解决?

解决SwiftUI中AnyShape数组遍历的Hashable兼容问题

你遇到的错误是因为ForEach使用id: \.self时,要求数组元素必须遵循Hashable协议,而AnyShape默认没有实现该协议。以下是几种可行的解决方法:


方法一:让AnyShape遵循Hashable协议

如果你的AnyShape是iOS16+提供的标准类型擦除包装器,或自定义的类似结构,可以通过扩展实现Hashable:

extension AnyShape: Hashable {
    public func hash(into hasher: inout Hasher) {
        // 利用内部包装的Shape进行哈希计算
        _box.hash(into: &hasher)
    }
    
    public static func == (lhs: AnyShape, rhs: AnyShape) -> Bool {
        // 比较内部包装的Shape是否相等
        lhs._box.isEqual(to: rhs._box)
    }
}

注:若为自定义AnyShape,将_box替换为你实际存储Shape的属性名即可。

修改后原ForEach代码可直接使用:

ForEach(viewModel.shapes, id: \.self) { shape in
    shape
        .fill(Color.blue)
        .frame(width: 100, height: 100)
}

方法二:用Identifiable结构体封装形状

这种方法无需修改AnyShape,通过包装结构体提供唯一标识,是更稳妥的动态数组解决方案:

  1. 创建遵循Identifiable的结构体:
struct IdentifiableShape: Identifiable {
    let id = UUID()
    var shape: AnyShape
}
  1. 更新ViewModel中的数组类型:
class ViewModel: ObservableObject {
    var shapes: [IdentifiableShape] = [
        IdentifiableShape(shape: .init(Rectangle())),
        IdentifiableShape(shape: .init(RoundedRectangle(cornerRadius: 10.0)))
    ]
}
  1. 简化View中的ForEach(Identifiable自动提供id):
struct ContentView: View {
    @StateObject var viewModel = ViewModel()
    
    var body: some View {
        ForEach(viewModel.shapes) { shapeItem in
            shapeItem.shape
                .fill(Color.blue)
                .frame(width: 100, height: 100)
        }
    }
}

方法三:使用数组索引作为ID(不推荐)

仅适用于静态数组(不会增删元素),数组元素顺序变化时会导致SwiftUI错误重用视图:

struct ContentView: View {
    @StateObject var viewModel = ViewModel()
    
    var body: some View {
        ForEach(viewModel.shapes.indices, id: \.self) { index in
            viewModel.shapes[index]
                .fill(Color.blue)
                .frame(width: 100, height: 100)
        }
    }
}

内容的提问来源于stack exchange,提问作者appfrosch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 13:55:19