你如何找出一个对象的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
。
这相当于isMemberOfClass
或isMemberOfClass
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”