是否有一种方法可以在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!


当前回答

编辑:在Swift 1.2 (Xcode 6.3)中引入了一个新的toString函数。

你现在可以使用.self和使用.dynamicType打印任意类型的需求类型:

struct Box<T> {}

toString("foo".dynamicType)            // Swift.String
toString([1, 23, 456].dynamicType)     // Swift.Array<Swift.Int>
toString((7 as NSNumber).dynamicType)  // __NSCFNumber

toString((Bool?).self)                 // Swift.Optional<Swift.Bool>
toString(Box<SinkOf<Character>>.self)  // __lldb_expr_1.Box<Swift.SinkOf<Swift.Character>>
toString(NSStream.self)                // NSStream

试着调用你的类。self和youobject . dynamictype。

参考:https://devforums.apple.com/thread/227425。

其他回答

你可以使用reflect来获取关于对象的信息。 例如对象类的名称:

var classname = reflect(now).summary

这在检查一个对象是否是类的类型时也很方便:

if someObject is SomeClass {
    //someObject is a type of SomeClass
}
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)")

我的运气是:

let className = NSStringFromClass(obj.dynamicType)

影响从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替换或正则表达式函数。

这只是我的个人意见。