你如何找出一个对象的types(在Swift中)?

当试图理解一个程序,或者在某些情况下,能够真正找出什么types是有用的。 我知道debugging器可以显示一些types信息,而且通常可以依靠types推断来避免在这些情况下不指定types,但是我仍然希望有类似Python的type()

dynamicType(查看这个问题 )

更新:在最近版本的Swift中已经改变了, obj.dynamicType现在给你提供了一个types的引用,而不是dynamictypes的实例。

这一个似乎是最有前途的,但到目前为止,我还没有能够找出实际的types

 class MyClass { var count = 0 } let mc = MyClass() # update: this now evaluates as true mc.dynamicType === MyClass.self 

我也尝试使用类引用来实例化一个新的对象,它可以工作,但奇怪地给了我一个错误,说我必须添加一个required初始化程序:

作品:

 class MyClass { var count = 0 required init() { } } let myClass2 = MyClass.self let mc2 = MyClass2() 

尽pipe如此,只是朝着真正发现任何给定对象的types迈出了一小步

编辑 :我已经删除了大量现在不相关的细节 – 查看编辑历史,如果你感兴趣:)

在Swift 2.0中,进行这种types内省的正确方法是使用Mirror结构 ,

  let stringObject:String = "testing" let stringArrayObject:[String] = ["one", "two"] let viewObject = UIView() let anyObject:Any = "testing" let stringMirror = Mirror(reflecting: stringObject) let stringArrayMirror = Mirror(reflecting: stringArrayObject) let viewMirror = Mirror(reflecting: viewObject) let anyMirror = Mirror(reflecting: anyObject) 

然后从Mirror结构访问types本身,你可以使用属性subjectType如下所示:

  // Prints "String" print(stringMirror.subjectType) // Prints "Array<String>" print(stringArrayMirror.subjectType) // Prints "UIView" print(viewMirror.subjectType) // Prints "String" print(anyMirror.subjectType) 

然后你可以使用这样的东西:

  if anyMirror.subjectType == String.self { print("anyObject is a string!") } else { print("anyObject is not a string!") } 

Swift 3版本:

 type(of: yourObject) 

“dynamicType.printClassName”代码来自Swift书中的一个例子。 我无法直接获取自定义类名,但可以使用“is”关键字来检查实例types,如下所示。 这个例子还展示了如何实现一个自定义的className函数,如果你真的想把类名作为一个string的话。

 class Shape { class func className() -> String { return "Shape" } } class Square: Shape { override class func className() -> String { return "Square" } } class Circle: Shape { override class func className() -> String { return "Circle" } } func getShape() -> Shape { return Square() // hardcoded for example } let newShape: Shape = getShape() newShape is Square // true newShape is Circle // false newShape.dynamicType.className() // "Square" newShape.dynamicType.className() == Square.className() // true 

请注意,NSObject的子类已经实现了自己的className函数。 如果你正在使用cocoa,你可以使用这个属性。

 class MyObj: NSObject { init() { super.init() println("My class is \(self.className)") } } MyObj() 

从Xcode 6.0.1(至less,不知道什么时候添加它),现在的原始示例工作:

 class MyClass { var count = 0 } let mc = MyClass() mc.dynamicType === MyClass.self // returns `true` 

更新:

为了回答原来的问题,你可以成功地使用Obj-C运行时和普通的Swift对象。

尝试以下操作:

 import Foundation class MyClass { } class SubClass: MyClass { } let mc = MyClass() let m2 = SubClass() // Both of these return .Some("__lldb_expr_35.SubClass"), which is the fully mangled class name from the playground String.fromCString(class_getName(m2.dynamicType)) String.fromCString(object_getClassName(m2)) // Returns .Some("__lldb_expr_42.MyClass") String.fromCString(object_getClassName(mc)) 

如果你只是需要检查variables是否是Xtypes的,或者它符合某个协议,那么你可以使用is ,还是as? 如下所示:

 var unknownTypeVariable = … if unknownTypeVariable is <ClassName> { //the variable is of type <ClassName> } else { //variable is not of type <ClassName> } 

这相当于Obj-C中的isKindOfClass

这相当于isMemberOfClassisMemberOfClass

 var unknownTypeVariable = … if let myClass = unknownTypeVariable as? <ClassName or ProtocolName> { //unknownTypeVarible is of type <ClassName or ProtocolName> } else { //unknownTypeVariable is not of type <ClassName or ProtocolName> } 

这在迅速工作3

 if unknownType is MyClass { //unknownType is of class type MyClass } 

以下是我推荐的两种方法:

 if let thisShape = aShape as? Square 

要么:

 aShape.isKindOfClass(Square) 

这里有一个详细的例子:

 class Shape { } class Square: Shape { } class Circle: Shape { } var aShape = Shape() aShape = Square() if let thisShape = aShape as? Square { println("Its a square") } else { println("Its not a square") } if aShape.isKindOfClass(Square) { println("Its a square") } else { println("Its not a square") } 

对于Swift 3.0

 String(describing: <Class-Name>.self) 

对于Swift 2.0 – 2.3

 String(<Class-Name>) 

取决于用例。 但是让我们假设你想用你的“variables”types做一些有用的事情。 Swift switch语句非常强大,可以帮助您获得所需的结果…

  let dd2 = ["x" : 9, "y" : "home9"] let dds = dd2.filter { let eIndex = "x" let eValue:Any = 9 var r = false switch eValue { case let testString as String: r = $1 == testString case let testUInt as UInt: r = $1 == testUInt case let testInt as Int: r = $1 == testInt default: r = false } return r && $0 == eIndex } 

在这种情况下,有一个简单的字典,其中包含可以是UInt,Int或String的键/值对。 在字典中的.filter()方法中,我需要确保正确地testing值,并且只在stringtesting时才testingstring等.filter()语句使得这个简单而安全! 通过给Anytypes的variables赋值9,它使Int执行切换。 尝试将其更改为:

  let eValue:Any = "home9" 

再试一次。 这一次它执行as String情况。

如果您收到“始终正确/失败”的警告,您可能需要在使用之前将其投射到任何is

 (foo as Any) is SomeClass 
 //: Playground - noun: a place where people can play import UIKit class A { class func a() { print("yeah") } func getInnerValue() { self.dynamicType.a() } } class B: A { override class func a() { print("yeah yeah") } } Ba() // yeah yeah Aa() // yeah B().getInnerValue() // yeah yeah A().getInnerValue() // yeah 
 let view = UIView() String(describing: type(of: view)) 

打印“UIView”