创建类似于 AnyHashable 的结构

问题描述 投票:0回答:1

我刚刚更新到 Xcode 16,由于将

AnyHashable
标记为不可发送,我的项目充满了警告。我在整个应用程序中依赖 AnyHashable,创建一个返回
UITableViewDiffableDataSource<Int, AnyHashable>
类型数据源的 ViewModel 层。现在我正在尝试构建一些可哈希和可发送的东西,并且可以在没有太多重构的情况下插入。参考网上的其他示例,我创建了这个以 AnyHashable 为模型的新结构

public struct AnyHashableSendable: Hashable, Sendable {
    
    public let base: any Hashable & Sendable
    
    public init<H>(_ base: H) where H : Hashable {
        self.base = base
    }
    
    public static func == (lhs: Self, rhs: Self) -> Bool {
        AnyHashable(lhs.base) == AnyHashable(rhs.base)
    }
    
    public func hash(into hasher: inout Hasher) {
        base.hash(into: &hasher)
    }
}

但是当前的实现带来了一些烦恼,我希望以与苹果实现相匹配的方式解决这些烦恼

  1. 如果我有一个类型为

    foo
    的变量
    AnyHashable
    并且我想转换它,我可以简单地执行
    let newBar = foo as? bar
    。但是对于类型为
    AnyHashableSendable
    的变量,我现在必须调用属性
    base
    来实现相同的目的,就像这样
    let newBar = foo.base as? bar
    一样。内置的 AnyHashable 如何避免调用其
    base
    属性?

  2. 如果我定义 AnyHashable 的数组或二维数组(

    [AnyHashable]
    [[AnyHashable]]
    ),我可以附加任何符合 hashable 的结构,它会自动转换它。例如

var array: [AnyHashable] = []
array.append(FooBar(prop1: "test", prop2: "test"))

但是对于 AnyHashableSendable,每个项目都必须初始化为新的对象类型,例如

var array: [AnyHashableSendable] = []
array.append(.init(FooBar(prop1: "test", prop2: "test")))


我尝试通过创建自己的自定义集合类型来解决至少第二个问题,并使用接受 AnyHashable 的重写函数并简单地调用 init 并存储它。虽然它有效,但差异需要大量的重构,并且也使用烦人的自定义代码/类型而不是现有逻辑。有没有一种我不知道的方法可以解决这两个问题,以便我的新类型像现有的 AnyHashable 一样运行?

ios swift generics xcode16 swift-hashable
1个回答
0
投票

您无法自己创建这样的类型。您提到的两种行为(直接向下转型和隐式转换为

AnyHashable
)都直接内置于编译器中。


根据 Swift GitHub 存储库中有关动态转换的 文档

AnyHashable
在转换上下文中的行为类似于存在类型,尽管它是
struct
。强制转换运算符可以“到达”存在的“盒子”内部并获取其中包含的实际值。

您可以在

DynamicCast.cpp
中找到AnyHashable的特殊情况,有对
_swift_anyHashableDownCastConditionalIndirect
的调用。这个函数是“伸手到盒子里”发生的地方。请参阅 AnyHashable.swift.

中的声明。

对于到

AnyHashable
的隐式转换,编译器插入一个名为
_convertToAnyHashable
的编译器内部函数,该函数也在 AnyHashable.swift 中声明,我认为 this 是发出它的行。

© www.soinside.com 2019 - 2024. All rights reserved.