如何在Swift中打印变量的类型或类?

365

有没有一种方法可以在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!的方法。

48
@JasonMArcher告诉我这个问题怎么是重复的,如果你链接的那个问题是在这个问题之后4天才被问到的? - akashivskyy
有关测试Swift对象类型或读取Swift对象类型的问题有很多。我们正在寻找最佳的问题作为该主题的“主问题”。建议的重复问题有更详细的答案。这并不是说你做错了什么,只是我们试图减少混乱。 - JasonMArcher
4
建议的重复问题并没有回答相同的问题;Type.self不能被打印到控制台用于调试目的,它应该被用于传递给其他将类型作为对象使用的函数。 - Matt Bridges
2
OT:非常奇怪,Swift没有提供这个功能,而且人们需要在这样的低级C库中摆弄。值得提交错误报告吗? - qwerty_so
各位,我已经提供了我的答案。请看一下并让我知道是否符合预期。 - DILIP KOSURI
34个回答

12

SWIFT 5

使用最新的Swift 3版本,我们可以通过String初始化器获取类型名称的漂亮描述,例如:print(String(describing: type(of: object)))。其中object可以是数组、字典、IntNSDate、自定义类的实例等实例变量。

这里是我的完整答案:获取Swift中对象的类名

该问题寻求一种将对象的类名作为字符串获取的方法,但我还提出了另一种获取不是NSObject子类变量的类名的方法。如下所示:

class Utility{
    class func classNameAsString(obj: Any) -> String {
        //prints more readable results for dictionaries, arrays, Int, etc
        return String(describing: type(of: obj))
    }
}

我写了一个静态函数,它以Any对象作为参数,并返回它的类名作为String :)。

我使用一些变量测试了这个函数,例如:

    let diccionary: [String: CGFloat] = [:]
    let array: [Int] = []
    let numInt = 9
    let numFloat: CGFloat = 3.0
    let numDouble: Double = 1.0
    let classOne = ClassOne()
    let classTwo: ClassTwo? = ClassTwo()
    let now = NSDate()
    let lbl = UILabel()

输出结果为:

  • 字典的类型是 Dictionary
  • 数组的类型是 Array
  • 整数的类型是 Int
  • 浮点数的类型是 CGFloat
  • 双精度浮点数的类型是 Double
  • 类 ClassOne 的类型是:ClassOne
  • 类 ClassTwo 的类型是:ClassTwo
  • 现在的时间类型是:Date
  • 标签 lbl 的类型是:UILabel

10

Xcode 8和Swift 3.0中

步骤:

1. 获取类型:

选项1:

let type : Type = MyClass.self  //Determines Type from Class

选项 2:

let type : Type = type(of:self) //Determines Type from self

2. 将类型转换为字符串:

let string : String = "\(type)" //String

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

7
为了在Swift中获取一个对象的类型或类,您需要使用 type(of: yourObject)

确认同样适用于Swift 5.4版本。 - Arindam Roychowdhury

5

最佳答案没有使用type(of: 的新方法的工作示例。所以为了帮助像我这样的新手,这里提供一个工作示例,主要取自苹果文档 - https://developer.apple.com/documentation/swift/2885064-type

doubleNum = 30.1

func printInfo(_ value: Any) {
    let varType = type(of: value)
    print("'\(value)' of type '\(varType)'")
}

printInfo(doubleNum)
//'30.1' of type 'Double'

5

在使用 Cocoa(而不是 CocoaTouch)时,您可以针对 NSObject 的子类使用 className 属性。

println(now.className)

这个属性对于普通的Swift对象不可用,因为它们不是NSObject的子类(事实上,在Swift中没有根id或对象类型)。

class Person {
    var name: String?
}

var p = Person()
println(person.className) // <- Compiler error

在CocoaTouch中,目前没有一种方法可以获取给定变量类型的字符串描述。在Cocoa或CocoaTouch中,原始类型也不存在类似的功能。Swift REPL能够打印出包括其类型的值摘要,因此未来可能通过API实现这种内省方式。
编辑:dump(object)似乎能够解决问题。

即使在Xcode 10和Swift 4.2中,dump(object)仍然非常强大。谢谢。 - Alex Zavatone

4

这里很多答案对于最新的Swift(编写时为Xcode 7.1.1)并不适用。

获取信息的当前方式是创建一个 Mirror 并进行查询。对于类名,只需这样简单操作:

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

还可以从Mirror中检索有关对象的其他信息。有关详细信息,请参见http://swiftdoc.org/v2.1/type/Mirror/


以下两个回答在 https://dev59.com/0mAg5IYBdhLWcg3wE3jQ#25345480 和 https://dev59.com/0mAg5IYBdhLWcg3wE3jQ#32087449 上似乎都能很好地与Swift 2一起使用,有什么问题吗?(没有检查其他答案。) - Martin R
我喜欢这个作为一般解决方案,但是出现了“ViewController的镜像”(多余的“镜像”)-等等,看起来使用“.subjectType”就可以解决问题! - David H

4

Swift 4 版本:

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

感谢 @Joshua Dance


4
在最新的XCode 6.3和Swift 1.2中,我找到了唯一的方法:
if view.classForCoder.description() == "UISegment" {
    ...
}

注意:description() 方法返回的类名格式为“<swift 模块名>.<实际类名>”,因此你需要通过点号(.)对字符串进行分割,获取最后一个 token。 - Matthew Quiros

4

我找到了以下解决方案,希望对其他人有用。 我创建了一个类方法来访问该值。请记住,这仅适用于NSObject的子类。但至少是一种干净整洁的解决方案。

class var className: String!{
    let classString : String = NSStringFromClass(self.classForCoder())
    return classString.componentsSeparatedByString(".").last;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接