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

Mat*_*ges 325 types swift

有没有办法在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
Run Code Online (Sandbox Code Playgroud)

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

Kla*_*aas 366

2016年9月更新

Swift 3.0:使用type(of:),例如type(of: someThing)(因为dynamicType关键字已被删除)

2015年10月更新:

我将下面的示例更新为新的Swift 2.0语法(例如,现在println替换为).printtoString()String()

从Xcode 6.3发行说明:

@nschum在评论中指出Xcode 6.3发行说明显示了另一种方式:

现在,当与println或字符串插值一起使用时,类型值将打印为完整的去格式类型名称.

import Foundation

class PureSwiftClass { }

var myvar0 = NSString() // Objective-C class
var myvar1 = PureSwiftClass()
var myvar2 = 42
var myvar3 = "Hans"

print( "String(myvar0.dynamicType) -> \(myvar0.dynamicType)")
print( "String(myvar1.dynamicType) -> \(myvar1.dynamicType)")
print( "String(myvar2.dynamicType) -> \(myvar2.dynamicType)")
print( "String(myvar3.dynamicType) -> \(myvar3.dynamicType)")

print( "String(Int.self)           -> \(Int.self)")
print( "String((Int?).self         -> \((Int?).self)")
print( "String(NSString.self)      -> \(NSString.self)")
print( "String(Array<String>.self) -> \(Array<String>.self)")
Run Code Online (Sandbox Code Playgroud)

哪个输出:

String(myvar0.dynamicType) -> __NSCFConstantString
String(myvar1.dynamicType) -> PureSwiftClass
String(myvar2.dynamicType) -> Int
String(myvar3.dynamicType) -> String
String(Int.self)           -> Int
String((Int?).self         -> Optional<Int>
String(NSString.self)      -> NSString
String(Array<String>.self) -> Array<String>
Run Code Online (Sandbox Code Playgroud)

Xcode 6.3更新:

你可以使用_stdlib_getDemangledTypeName():

print( "TypeName0 = \(_stdlib_getDemangledTypeName(myvar0))")
print( "TypeName1 = \(_stdlib_getDemangledTypeName(myvar1))")
print( "TypeName2 = \(_stdlib_getDemangledTypeName(myvar2))")
print( "TypeName3 = \(_stdlib_getDemangledTypeName(myvar3))")
Run Code Online (Sandbox Code Playgroud)

并将此作为输出:

TypeName0 = NSString
TypeName1 = __lldb_expr_26.PureSwiftClass
TypeName2 = Swift.Int
TypeName3 = Swift.String
Run Code Online (Sandbox Code Playgroud)

原始答案:

在Xcode 6.3之前_stdlib_getTypeName获得变量的错位类型名称.Ewan Swick的博客文章有助于破译这些字符串:

例如_TtSi代表Swift的内部Int类型.

Mike Ash有一篇很棒的博客文章,涵盖了相同的主题.

  • 看起来我可以在repl中轻松地用`lldb`搜索符号.还有`_stdlib_getDemangledTypeName()`和`_stdlib_demangleName()`. (10认同)
  • Swift 3.0:`dynamicType`关键字已从Swift中删除.取而代之的是,语言中添加了一个新的原始函数`type(of:)`:https://github.com/apple/swift/blob/master/CHANGELOG.md (6认同)
  • 你是怎么找到`_stdlib_getTypeName()`的?集成的R​​EPL不再存在,`swift-ide-test`也不存在,并且Xcode的Swift模块的打印省略了`_`-前缀值. (2认同)

aka*_*kyy 45

编辑:Swift 1.2(Xcode 6.3)中引入了一个新toString功能.

现在,您可以打印demangled类型使用任何类型的.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
Run Code Online (Sandbox Code Playgroud)

试着打电话YourClass.selfyourObject.dynamicType.

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

  • printClassName()方法只是他们在文档中的一个示例中创建的示例方法,它不是您可以访问的API调用. (18认同)
  • 仅供参考 - 看起来toString(...)已被String(...)取代 (4认同)
  • 我回复了那个帖子,但我会在这里添加我的评论.这些值的类型为"Metatype",但似乎没有一种简单的方法来确定Metatype对象代表什么类型,这正是我正在寻找的. (2认同)

Evg*_*nii 31

Swift 3.0

let string = "Hello"
let stringArray = ["one", "two"]
let dictionary = ["key": 2]

print(type(of: string)) // "String"

// Get type name as a string
String(describing: type(of: string)) // "String"
String(describing: type(of: stringArray)) // "Array<String>"
String(describing: type(of: dictionary)) // "Dictionary<String, Int>"

// Get full type as a string
String(reflecting: type(of: string)) // "Swift.String"
String(reflecting: type(of: stringArray)) // "Swift.Array<Swift.String>"
String(reflecting: type(of: dictionary)) // "Swift.Dictionary<Swift.String, Swift.Int>"
Run Code Online (Sandbox Code Playgroud)


Hai*_*ezu 30

这是你在找什么?

println("\(object_getClassName(now))");
Run Code Online (Sandbox Code Playgroud)

它打印"__NSDate"

更新:请注意,这似乎不再适用于Beta05

  • 不适用于ObjC类(至少在Beta5中),对于NSManagedObject,我只得到"Builtin.RawPointer = address" (4认同)
  • 不适用于快速课程.返回"UnsafePointer(0x7FBB18D06DE0)" (2认同)

Mat*_*gen 23

我目前的Xcode是6.0版(6A280e).

import Foundation

class Person { var name: String; init(name: String) { self.name = name }}
class Patient: Person {}
class Doctor: Person {}

var variables:[Any] = [
    5,
    7.5,
    true,
    "maple",
    Person(name:"Sarah"),
    Patient(name:"Pat"),
    Doctor(name:"Sandy")
]

for variable in variables {
    let typeLongName = _stdlib_getDemangledTypeName(variable)
    let tokens = split(typeLongName, { $0 == "." })
    if let typeName = tokens.last {
        println("Variable \(variable) is of Type \(typeName).")
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

Variable 5 is of Type Int.
Variable 7.5 is of Type Double.
Variable true is of Type Bool.
Variable maple is of Type String.
Variable Swift001.Person is of Type Person.
Variable Swift001.Patient is of Type Patient.
Variable Swift001.Doctor is of Type Doctor.
Run Code Online (Sandbox Code Playgroud)


kid*_*ing 18

从使用Swift 1.2的Xcode 6.3开始,您可以简单地将类型值转换为完全解码String.

toString(Int)                   // "Swift.Int"
toString(Int.Type)              // "Swift.Int.Type"
toString((10).dynamicType)      // "Swift.Int"
println(Bool.self)              // "Swift.Bool"
println([UTF8].self)            // "Swift.Array<Swift.UTF8>"
println((Int, String).self)     // "(Swift.Int, Swift.String)"
println((String?()).dynamicType)// "Swift.Optional<Swift.String>"
println(NSDate)                 // "NSDate"
println(NSDate.Type)            // "NSDate.Type"
println(WKWebView)              // "WKWebView"
toString(MyClass)               // "[Module Name].MyClass"
toString(MyClass().dynamicType) // "[Module Name].MyClass"
Run Code Online (Sandbox Code Playgroud)


Lea*_*ros 17

您仍然可以通过className(返回a String)访问该类.

实际上,有几种方法来获取类,例如classForArchiver,classForCoder,classForKeyedArchiver(都返回AnyClass!).

您无法获取基元的类型(基元不是类).

例:

var ivar = [:]
ivar.className // __NSDictionaryI

var i = 1
i.className // error: 'Int' does not have a member named 'className'
Run Code Online (Sandbox Code Playgroud)

如果要获取基元的类型,则必须使用bridgeToObjectiveC().例:

var i = 1
i.bridgeToObjectiveC().className // __NSCFNumber
Run Code Online (Sandbox Code Playgroud)

  • className似乎仅在为OSX开发时可用于NSObjects; 它在iOS SDK中不适用于NSObject或"普通"对象 (9认同)
  • `className`是Cocoa的AppleScript支持的一部分,绝对不应该用于通用内省.显然它不适用于iOS. (3认同)

Sta*_*tan 16

您可以使用反射来获取有关对象的信息.
例如对象类的名称:

var classname = reflect(now).summary


mxc*_*xcl 13

我好运:

let className = NSStringFromClass(obj.dynamicType)
Run Code Online (Sandbox Code Playgroud)


Har*_*war 12

Xcode 8 Swift 3.0使用类型(:)

let className = "\(type(of: instance))"
Run Code Online (Sandbox Code Playgroud)


use*_*037 10

在Xcode 8中,Swift 3.0

脚步:

1.获取类型:

选项1:

let type : Type = MyClass.self  //Determines Type from Class
Run Code Online (Sandbox Code Playgroud)

选项2:

let type : Type = type(of:self) //Determines Type from self
Run Code Online (Sandbox Code Playgroud)

2.将Type转换为String:

let string : String = "\(type)" //String
Run Code Online (Sandbox Code Playgroud)


小智 8

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


mau*_*nde 7

SWIFT 3

使用最新版本的Swift 3,我们可以通过String初始化程序获得类型名称的漂亮描述.比如,例如print(String(describing: type(of: object))).哪里object 可以是实例变量,如数组,字典,a Int,a NSDate,自定义类的实例等.

这是我的完整答案:在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))
    }
}
Run Code Online (Sandbox Code Playgroud)

我创建了一个静态函数,它将参数作为类型的对象,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()
Run Code Online (Sandbox Code Playgroud)

输出是:

  • diccionary是Dictionary类型
  • array的类型为Array
  • numInt的类型为Int
  • numFloat的类型为CGFloat
  • numDouble的类型为Double
  • classOne的类型为:ClassOne
  • classTwo的类型为:ClassTwo
  • 现在是类型:日期
  • lbl的类型:UILabel


Rah*_*ade 7

要在Swift中获取对象类型对象类,您必须使用type(of: yourObject)

类型(您的对象)


Mat*_*ges 5

使用Cocoa(而非CocoaTouch)时,可以将className属性用于NSObject子类的对象。

println(now.className)
Run Code Online (Sandbox Code Playgroud)

此属性不适用于普通的Swift对象,这些对象不是NSObject的子类(实际上,Swift中没有根ID或对象类型)。

class Person {
    var name: String?
}

var p = Person()
println(person.className) // <- Compiler error
Run Code Online (Sandbox Code Playgroud)

在CocoaTouch中,目前尚无法获取给定变量类型的字符串描述。对于Cocoa或CocoaTouch中的原始类型,也不存在类似的功能。

Swift REPL能够打印出包括其类型的值的摘要,因此将来有可能通过API进行这种自省。

编辑dump(object)似乎可以解决问题。


Jos*_*nce 5

最佳答案没有使用新方法的工作示例type(of:.所以为了帮助像我这样的新手,这里有一个很好的例子,主要来自Apple的文档 - 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'
Run Code Online (Sandbox Code Playgroud)