用于检查大小写的 Swift 通用枚举函数

标签 swift

如果枚举实例是枚举类型,是否可以创建一个返回 bool 值的通用枚举函数,或者它是否已经存在但我不知道?


我在我的项目中使用了大量的枚举。我经常定义具有关联值的枚举。

简单示例:

enum Mode {
    case new
    case edit(Record)    // Record is a struct type
}

我会定期检查枚举实例是否是特定的枚举案例。然而,很多时候,我不需要检查关联值。我正在寻找一种方便的方法来检查案例。我所知道的每种方法都有缺点。

方法1-2:If Case模式匹配或Switch case

let myMode = Mode.edit
if case Mode.edit(_) = myMode {
    // do something
}

switch mode {
case .edit:
    // do something
default:
    break    
}

缺点:

  • 不能直接将检查分配给变量。必须在结束时这样做
  • 不能将此模式直接用作函数的参数

方法3-5 实现枚举函数或检查计算属性或Equatable协议(protocol)的值

缺点:

  • 必须为每个枚举类型实现

相反,我正在寻找一种方法来编写一个通用函数,该函数在枚举实例与枚举大小写匹配时返回 bool 值。可以编写一次并应用于所有枚举的东西。类似于结构和类类型的泛型函数:

func checkType<T, S> (a: T, _: S.Type) -> Bool {

    return a is S   // though you could just call this directly
}

最佳答案

我认为没有一种好的惯用方法可以实现这一点。唯一想到的是将枚举实例的原始内存与具有所需情况的虚拟实例进行比较。

因为我们不关心关联值,所以我们只需要要求它们各自的最后一个字节相同。

func unsafeEqualityLastByteOnly<A>(_ lhs: A, _ rhs: A) -> Bool {
    var (lhs, rhs) = (lhs, rhs)

    let offset = MemoryLayout<A>.size - 1

    return withUnsafePointer(to: &lhs) { lhsPtr in
        withUnsafePointer(to: &rhs) { rhsPtr in
            let lhsPtr = unsafeBitCast(lhsPtr, to: UnsafeRawPointer.self)
            let rhsPtr = unsafeBitCast(rhsPtr, to: UnsafeRawPointer.self)

            return memcmp(lhsPtr.advanced(by: offset), rhsPtr.advanced(by: offset), 1) == 0
        }
    }
}

这远非漂亮,但它有效。

enum Test {
    case a(Int)
    case b(Int)
}

let a1 = Test.a(1)
let a2 = Test.a(2)

let b1 = Test.b(1)
let b2 = Test.b(2)

unsafeEqualityLastByteOnly(a1, a1) // true
unsafeEqualityLastByteOnly(a1, a2) // true
unsafeEqualityLastByteOnly(a2, a2) // true

unsafeEqualityLastByteOnly(b1, b1) // true
unsafeEqualityLastByteOnly(b1, b2) // true
unsafeEqualityLastByteOnly(b2, b2) // true

unsafeEqualityLastByteOnly(a1, b1) // false
unsafeEqualityLastByteOnly(a1, b2) // false
unsafeEqualityLastByteOnly(a2, b1) // false
unsafeEqualityLastByteOnly(a2, b2) // false

根据您自己的判断来决定这是否是您想要在您的项目中使用的东西。这显然不是一种应该毫无保留地推荐的技术。

关于用于检查大小写的 Swift 通用枚举函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43022999/

相关文章:

ios - UIDocumentPickerViewController 未调用 documentPicker 委托(delegate)

ios - 如果输入一个给定的 ViewController,如何删除 TabBar

ios - 从子类在 Swift 中具有泛型的基类转换子类

swift - DynamoDB Swift 表扫描映射类

ios - 如何在静态 TableViewCell 中显示 UICollectionView?

swift - Swift 3 中的 TableViewCell 复制属性已更改

ios - MPMusicPlayerController.play() 在杀死 iOS 音乐应用程序后无法正常工作

swift - 如何循环按钮

ios - UICollectionView header 上的 UITapGestureRecognizer 不起作用?

ios - 如何在 Swift 中将枚举和 switch() 与 UITableViewController 一起使用