给出方法
func enumCaseCount<T: Hashable>(ofType type: T.Type) -> Int {
// Needed check if type is an enum type
return 3
}
使用如下
private enum SimpleEnum: String {
case a = "A"
case b = "B"
case c = "C"
}
enumCaseCount(ofType: SimpleEnum.self)
可以通过这种方式测试类
class Test {}
Test.self is AnyClass // returns true
答案 0 :(得分:2)
为了它的乐趣,作为(变通方法)黑客,我们可以实例化T
的实例,并使用Mirror
对其进行运行时检查,特别是{ {3}}财产。在我们继续之前,我们注意到我们只会将其用于调试目的
镜子由游乐场和调试器使用。
我还要指出,我们在这里真正追逐我们的尾巴,因为我们在编译时使用运行时来查询已知的内容(至少是编译器)。
无论如何,首先,我将enumCaseCount(...)
重命名为isEnum(...)
,因为此问题仅涵盖查询元组类型是否为enum
。对于查询给定enum
的案例数量的类似(稍微脆弱)的黑客攻击,请参阅:
现在,T
中的通用占位符isEnum(...)
只知道它是符合How do I get the count of a Swift enum?的类型,它没有给我们任何直接的实例化方法。 T
的实例(如果Hashable
蓝图,例如,初始值设定项init()
,我们可以很容易地构造T
实例运行时内省的实例。相反,我们将为单个T
实例(Hashable
)手动分配原始内存,将其绑定到T
(UnsafeMutableRawPointer.allocate(bytes:alignedTo:)
),最后取消分配内存(bindMemory(to:capacity:)
)一旦我们完成了对绑定内存指针引用的实例的运行时内省。至于运行时内省,我们只需使用Mirror
来检查其displayStyle
是否为enum
。
func isEnum<T: Hashable>(_: T.Type) -> Bool {
var result = false
// Allocate memory with size and alignment matching T.
let bytesPointer = UnsafeMutableRawPointer.allocate(
bytes: MemoryLayout<T>.size,
alignedTo: MemoryLayout<T>.alignment)
// Bind memory to T and perform introspection on the instance
// reference to by the bound memory.
if case .some(.`enum`) = Mirror(reflecting:
bytesPointer.bindMemory(to: T.self, capacity: 1).pointee)
.displayStyle {
print("Is an enum")
result = true
} else { print("Is not an enum") }
// Deallocate the manually allocate memory.
bytesPointer.deallocate(bytes: MemoryLayout<T>.size,
alignedTo: MemoryLayout<T>.alignment)
return result
}
使用示例:
enum SimpleEnum { case a, b, c }
enum SimpleStrEnum: String {
case a = "A"
case b = "B"
case c = "C"
}
enum SimpleExplicitIntEnum: Int { case a, b, c }
struct SimpleStruct: Hashable {
let i: Int
// Hashable
var hashValue: Int { return 0 }
static func ==(lhs: SimpleStruct, rhs: SimpleStruct) -> Bool { return true }
}
print(isEnum(SimpleEnum.self)) // true
print(isEnum(SimpleStrEnum.self)) // true
print(isEnum(SimpleExplicitIntEnum.self)) // true
print(isEnum(SimpleStruct.self)) // false
答案 1 :(得分:1)
正如其他人所说,在Swift中没有很好的非hacky方法。但是,它是Sourcery的一个示例用例,一个元编程库(这意味着它会分析您的代码以生成其他代码)。您编写Stencil模板来描述其行为,并将其作为Xcode中的构建阶段执行。它可以为项目中找到的任何枚举自动生成此代码。
答案 2 :(得分:1)
要检查某种类型是否实际上是枚举,可以使用:
func isEnum<T>(_ type: T.Type) -> Bool {
let ptr = unsafeBitCast(T.self as Any.Type, to: UnsafeRawPointer.self)
return ptr.load(as: Int.self) == 513
}
您可以像这样简单地使用它:
enum MyEnum {}
struct MyStruct {}
class MyClass {}
isEnum(MyEnum.self) // this returns true
isEnum(MyStruct.self) // this returns false
isEnum(MyClass.self) // this returns false
在您的示例中,您将像这样使用它:
func enumCaseCount<T: Hashable>(ofType type: T.Type) -> Int {
isEnum(T.self) // returns true if enum
return 3
}