是否有一种方法可以在swift中打印变量的运行时类型?例如:

var now = NSDate()
var soon = now.dateByAddingTimeInterval(5.0)

println("\(now.dynamicType)") 
// Prints "(Metatype)"

println("\(now.dynamicType.description()")
// Prints "__NSDate" since objective-c Class objects have a "description" selector

println("\(soon.dynamicType.description()")
// Compile-time error since ImplicitlyUnwrappedOptional<NSDate> has no "description" method

在上面的例子中,我正在寻找一种方法来显示变量“soon”的类型是ImplicitlyUnwrappedOptional<NSDate>,或至少NSDate!


当前回答

let i: Int = 20


  func getTypeName(v: Any) -> String {
    let fullName = _stdlib_demangleName(_stdlib_getTypeName(i))
    if let range = fullName.rangeOfString(".") {
        return fullName.substringFromIndex(range.endIndex)
    }
    return fullName
}

println("Var type is \(getTypeName(i)) = \(i)")

其他回答

这里的许多答案都不支持最新的Swift(本文撰写时为Xcode 7.1.1)。

目前获取信息的方法是创建一个Mirror并对其进行询问。对于类名,它很简单:

let mirror = Mirror(reflecting: instanceToInspect)
let classname:String = mirror.description

关于对象的其他信息也可以从镜像中检索。详情见http://swiftdoc.org/v2.1/type/Mirror/。

在Swift 3.0中,你可以使用type(of:),因为dynamicType关键字已被删除。

Swift版本4:

print("\(type(of: self)) ,\(#function)")
// within a function of a class

谢谢@Joshua Dance

影响从String(description: type(of: self))返回的类名的另一个重要方面是Access Control。

考虑以下例子,基于Swift 3.1.1, Xcode 8.3.3(2017年7月)

func printClassNames() {

    let className1 = SystemCall<String>().getClassName()
    print(className1) // prints: "SystemCall<String>"

    let className2 = DemoSystemCall().getClassName()
    print(className2) // prints: "DemoSystemCall"

    // private class example
    let className3 = PrivateDemoSystemCall().getClassName()
    print(className3) // prints: "(PrivateDemoSystemCall in _0FC31E1D2F85930208C245DE32035247)" 

    // fileprivate class example
    let className4 = FileprivateDemoSystemCall().getClassName()
    print(className4) // prints: "(FileprivateDemoSystemCall in _0FC31E1D2F85930208C245DE32035247)" 
}

class SystemCall<T> {
    func getClassName() -> String {
        return String(describing: type(of: self))
    }
}

class DemoSystemCall: SystemCall<String> { }

private class PrivateDemoSystemCall: SystemCall<String> { }

fileprivate class FileprivateDemoSystemCall: SystemCall<String> { }

如您所见,本例中的所有类都有不同级别的访问控制,这些访问控制会影响它们的String表示。如果类有私有或文件私有的访问控制级别,Swift似乎会附加一些与类的“嵌套”类相关的标识符。

PrivateDemoSystemCall和FileprivateDemoSystemCall的结果是附加了相同的标识符,因为它们都嵌套在同一个父类中。

我还没有找到一种方法来摆脱,除了一些hack替换或正则表达式函数。

这只是我的个人意见。

Xcode 8 Swift 3.0使用类型:

let className = "\(type(of: instance))"