Как напечатать тип или class переменной в 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 has no "description" method 

В приведенном выше примере я ищу способ показать, что переменная «скоро» имеет тип ImplicitlyUnwrappedOptional или, по крайней мере, NSDate! ,

Обновление сентября 2016 года

Swift 3.0: Используйте type(of:) , например, type(of: someThing) (поскольку ключевое слово dynamicType было удалено)

Обновление октября 2015 года :

Я обновил приведенные ниже примеры до нового синтаксиса Swift 2.0 (например, println был заменен на print , toString() теперь – String() ).

Из примечаний к выпуску Xcode 6.3 :

@nschum отмечает в комментариях, что примечания к выпуску Xcode 6.3 показывают другой способ:

Значения типов теперь печатаются как полное имя demangled типа при использовании с 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.self) -> \(Array.self)") 

Какие результаты:

 String(myvar0.dynamicType) -> __NSCFConstantString String(myvar1.dynamicType) -> PureSwiftClass String(myvar2.dynamicType) -> Int String(myvar3.dynamicType) -> String String(Int.self) -> Int String((Int?).self -> Optional String(NSString.self) -> NSString String(Array.self) -> Array 

Обновление для 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))") 

и получить это как вывод:

 TypeName0 = NSString TypeName1 = __lldb_expr_26.PureSwiftClass TypeName2 = Swift.Int TypeName3 = Swift.String 

Оригинальный ответ:

До Xcode 6.3 _stdlib_getTypeName получил _stdlib_getTypeName имя переменной. Запись блога Ewan Swick помогает расшифровать эти строки:

например, _TtSi обозначает внутренний тип Int типа Swift.

У Майка Эша замечательная запись в блоге, посвященная той же теме .

Изменить: новая функция toString была введена в Swift 1.2 (Xcode 6.3) .

Теперь вы можете напечатать тип demangled любого типа, используя .self и любой экземпляр, используя .dynamicType :

 struct Box {} toString("foo".dynamicType) // Swift.String toString([1, 23, 456].dynamicType) // Swift.Array toString((7 as NSNumber).dynamicType) // __NSCFNumber toString((Bool?).self) // Swift.Optional toString(Box>.self) // __lldb_expr_1.Box> toString(NSStream.self) // NSStream 

Попробуйте вызвать YourClass.self и yourObject.dynamicType .

Ссылка: https://devforums.apple.com/thread/227425 .

Это то, что вы ищете?

 println("\(object_getClassName(now))"); 

Он печатает “__NSDate”

ОБНОВЛЕНИЕ : Обратите внимание, что это больше не работает с Beta05

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(describing: type(of: dictionary)) // "Dictionary" // Get full type as a string String(reflecting: type(of: string)) // "Swift.String" String(reflecting: type(of: stringArray)) // "Swift.Array" String(reflecting: type(of: dictionary)) // "Swift.Dictionary" 

Мой текущий 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).") } } 

Вывод:

 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. 

Начиная с Xcode 6.3 с Swift 1.2, вы можете просто преобразовать значения типа в полную demringled 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" println((Int, String).self) // "(Swift.Int, Swift.String)" println((String?()).dynamicType)// "Swift.Optional" println(NSDate) // "NSDate" println(NSDate.Type) // "NSDate.Type" println(WKWebView) // "WKWebView" toString(MyClass) // "[Module Name].MyClass" toString(MyClass().dynamicType) // "[Module Name].MyClass" 

Вы все равно можете получить доступ к classу через className (который возвращает String ).

На самом деле существует несколько способов получить class, например classForArchiver , classForCoder , classForKeyedArchiver (все возвращают AnyClass! ).

Вы не можете получить тип примитива (примитив – это не class).

Пример:

 var ivar = [:] ivar.className // __NSDictionaryI var i = 1 i.className // error: 'Int' does not have a member named 'className' 

Если вы хотите получить тип примитива, вы должны использовать bridgeToObjectiveC() . Пример:

 var i = 1 i.bridgeToObjectiveC().className // __NSCFNumber 

Вы можете использовать отображение, чтобы получить информацию об объекте.
Например, имя classа объекта:

 var classname = отражает (сейчас) .summary

Мне повезло:

 let className = NSStringFromClass(obj.dynamicType) 

Тип использования Xcode 8 Swift 3.0 (из 🙂

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

В 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 

В Swift 3.0 вы можете использовать type(of:) , поскольку dynamicType слово dynamicType было удалено.

SWIFT 3

С последним выпуском Swift 3 мы можем получить красивые описания имен типов с помощью инициализатора String . Например, print(String(describing: type(of: object))) . Где object может быть переменным экземпляра, например массивом, словарем, Int , NSDate , экземпляром пользовательского classа и т. Д.

Вот мой полный ответ: Получить имя classа объекта как строку в Swift

Этот вопрос ищет способ получить имя classа объекта как строку, но также я предложил другой способ получить имя classа переменной, которая не является подclassом 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 и возвращает его имя classа как 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() 

и выход был:

  • дичионарий имеет тип Словарь
  • array имеет тип Array
  • numInt имеет тип Int
  • numFloat имеет тип CGFloat
  • numDouble имеет тип Double
  • classOne имеет тип: ClassOne
  • classTwo имеет тип: ClassTwo
  • теперь имеет тип: Дата
  • lbl имеет тип: UILabel

При использовании Cocoa (не CocoaTouch) вы можете использовать свойство className для объектов, которые являются подclassами NSObject.

 println(now.className) 

Это свойство недоступно для обычных объектов Swift, которые не являются подclassами NSObject (и на самом деле в Swift нет корневого идентификатора или типа объекта).

 class Person { var name: String? } var p = Person() println(person.className) // <- Compiler error 

В CocoaTouch в настоящее время нет способа получить строковое описание типа данной переменной. Подобная функциональность также не существует для примитивных типов в Cocoa или CocoaTouch.

Swift REPL может распечатать сводку значений, включая ее тип, поэтому возможно, что этот способ самоанализа будет возможен через API в будущем.

EDIT : dump(object) похоже, делает трюк.

Я попробовал некоторые другие ответы здесь, но milage, похоже, очень относится к тому, что является объектом underling.

Однако я нашел способ, которым вы можете получить имя classа Object-C для объекта, выполнив следующее:

 now?.superclass as AnyObject! //replace now with the object you are trying to get the class name for 

Вот и пример того, как вы его используете:

 let now = NSDate() println("what is this = \(now?.superclass as AnyObject!)") 

В этом случае он будет печатать NSDate в консоли.

Я нашел это решение, которое, надеюсь, может работать для кого-то другого. Я создал метод classа для доступа к значению. Пожалуйста, имейте в виду, что это будет работать только для подclassа NSObject. Но, по крайней мере, это чистое и аккуратное решение.

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

В последнем XCode 6.3 с Swift 1.2 это единственный способ, которым я нашел:

 if view.classForCoder.description() == "UISegment" { ... } 

В lldb с бета-версии 5 вы можете увидеть class объекта с помощью команды:

 fr v -dr shipDate 

который выводит что-то вроде:

 (DBSalesOrderShipDate_DBSalesOrderShipDate_ *) shipDate = 0x7f859940 

Расширение команды означает что-то вроде:

Frame Variable (печать переменной кадра) -d run_target (расширение динамических типов)

Что-то полезное, чтобы знать, что использование «Frame Variable» для вывода значений переменных гарантирует, что код не будет выполнен.

Я нашел решение для саморазвитых classов (или у вас есть доступ).

Поместите следующее вычисляемое свойство в определение classа объектов:

 var className: String? { return __FILE__.lastPathComponent.stringByDeletingPathExtension } 

Теперь вы можете просто вызвать имя classа на своем объекте так:

 myObject.className 

Обратите внимание, что это будет работать только в том случае, если определение classа выполняется в файле, который называется точно так же, как class, для которого вы хотите использовать имя.

Как это обычно бывает, вышеупомянутый ответ должен сделать это для большинства случаев . Но в некоторых особых случаях вам может понадобиться выяснить другое решение.


Если вам нужно имя classа внутри самого classа (файла), вы можете просто использовать эту строку:

 let className = __FILE__.lastPathComponent.stringByDeletingPathExtension 

Возможно, этот метод помогает некоторым людям.

Основываясь на ответах и ​​комментариях, полученных Классом и Кевином Баллардом выше, я хотел бы:

 println(_stdlib_getDemangledTypeName(now).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon?).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon!).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar0).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar1).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar2).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar3).componentsSeparatedByString(".").last!) -то println(_stdlib_getDemangledTypeName(now).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon?).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon!).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar0).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar1).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar2).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar3).componentsSeparatedByString(".").last!) -то println(_stdlib_getDemangledTypeName(now).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon?).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon!).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar0).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar1).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar2).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar3).componentsSeparatedByString(".").last!) -то println(_stdlib_getDemangledTypeName(now).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon?).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon!).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar0).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar1).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar2).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar3).componentsSeparatedByString(".").last!) -то println(_stdlib_getDemangledTypeName(now).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon?).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon!).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar0).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar1).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar2).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar3).componentsSeparatedByString(".").last!) -то println(_stdlib_getDemangledTypeName(now).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon?).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon!).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar0).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar1).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar2).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar3).componentsSeparatedByString(".").last!) -то println(_stdlib_getDemangledTypeName(now).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon?).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon!).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar0).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar1).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar2).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar3).componentsSeparatedByString(".").last!) -то println(_stdlib_getDemangledTypeName(now).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon?).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(soon!).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar0).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar1).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar2).componentsSeparatedByString(".").last!) println(_stdlib_getDemangledTypeName(myvar3).componentsSeparatedByString(".").last!) 

который распечатает:

 "NSDate" "ImplicitlyUnwrappedOptional" "Optional" "NSDate" "NSString" "PureSwiftClass" "Int" "Double" 
 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 и опросить его. Для имени classа это просто:

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

Дополнительная информация об объекте также может быть получена из Mirror . Подробнее см. http://swiftdoc.org/v2.1/type/Mirror/ .

В верхнем ответе нет рабочего примера нового способа сделать это с помощью type(of: . Итак, чтобы помочь новичкам вроде меня, вот рабочий пример, взятый в основном из документов Apple здесь – https://developer.apple .com / документация / быстрое / 2885064-типа

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

По-видимому, не существует общего способа печати типа имени типа произвольного значения. Как отмечали другие, для экземпляров classов вы можете печатать value.className но для примитивных значений появляется, что во время выполнения информация о типе исчезла.

Например, похоже, что нет способа напечатать: 1.something() и вытащить Int за любую ценность something . (Вы можете, как сказал другой ответ, использовать i.bridgeToObjectiveC().className чтобы дать вам подсказку, но __NSCFNumber самом деле не тип i – именно то, что он будет преобразован, когда он пересекает границу объекта Objective- C).

Я был бы рад оказаться ошибочным, но похоже, что проверка типов выполняется во время компиляции, и, как и C ++ (с отключенным RTTI), большая часть информации о типе отсутствует во время выполнения.

Не совсем то, что вам нужно, но вы также можете проверить тип переменной по типам Swift:

 let object: AnyObject = 1 if object is Int { } else if object is String { } 

Например.

Xcode 7.3.1, Swift 2.2:

String(instanceToPrint.self).componentsSeparatedByString(".").last

Swift 3.0, Xcode 8

В следующем коде вы можете запросить экземпляр для своего classа. Вы также можете сравнить два экземпляра, имеющих один class.

 // CREATE pure SWIFT class class MySwiftClass { var someString : String = "default" var someInt : Int = 5 } // CREATE instances let firstInstance = MySwiftClass() let secondInstance = MySwiftClass() secondInstance.someString = "Donald" secondInstance.someInt = 24 // INSPECT instances if type(of: firstInstance) === MySwiftClass.self { print("SUCCESS with ===") } else { print("PROBLEM with ===") } if type(of: firstInstance) == MySwiftClass.self { print("SUCCESS with ==") } else { print("PROBLEM with ==") } // COMPARE CLASS OF TWO INSTANCES if type(of: firstInstance) === type(of: secondInstance) { print("instances have equal class") } else { print("instances have NOT equal class") } 

Быстрая версия 4:

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

Спасибо @ Joshua Dance

Вот как вы получаете строку типа вашего объекта или типа, который является согласованным и учитывает, к какому модулю относится определение объекта или nested. Работает в Swift 4.x.

 @inline(__always) func typeString(for _type: Any.Type) -> String { return String(reflecting: type(of: _type)) } @inline(__always) func typeString(for object: Any) -> String { return String(reflecting: type(of: type(of: object))) } struct Lol { struct Kek {} } // if you run this in playground the results will be something like typeString(for: Lol.self) // __lldb_expr_74.Lol.Type typeString(for: Lol()) // __lldb_expr_74.Lol.Type typeString(for: Lol.Kek.self)// __lldb_expr_74.Lol.Kek.Type typeString(for: Lol.Kek()) // __lldb_expr_74.Lol.Kek.Type 

Это также удобно при проверке, является ли объект типом classа:

 if someObject is SomeClass { //someObject is a type of SomeClass } 
  • Преобразовать строку в тип C #
  • .NET Integer vs Int16?
  • PostgreSQL: разница между текстом и varchar (характер меняется)
  • Как обращаться с неправильным вводом типа данных
  • Scala: Что такое TypeTag и как его использовать?
  • Когда использовать значения без знака над подписанными?
  • Что такое экзистенциальный тип?
  • Как определить разные типы для одного и того же classа в C ++
  • Как проверить, наследует ли class другой class, не создавая его?
  • Производительность TypeCasting
  • Тестирование, если объект имеет общий тип в C #
  • Interesting Posts

    Электронная почта Java regex

    Как преобразовать значения big-endian и little-endian в C ++?

    SQL-запрос возвращает данные из нескольких таблиц

    Как читать файл с определенного смещения в Java?

    Почему анонимный внутренний class не содержит ничего из этого кода?

    Машина Window 8 не может пинговать устройства в одной подсети

    Добавить драйверы сетевого принтера в Windows 7 / Server 2008 R2?

    В чем разница между абстрактным деревом синтаксиса и деревом синтаксиса бетона?

    застрял в получении снимка камеры при использовании вкладки «Активность»

    Используйте автофильтр по более чем 2 критериям

    Как проверить форматирование адресов электронной почты с помощью .NET Framework?

    Почему реализация libc ++ std :: string занимает 3-кратную память как libstdc ++?

    как реплицировать массив

    Чтение больших текстовых файлов с streamами в C #

    Каков наилучший способ сделать подстроку в пакетном файле?

    Давайте будем гением компьютера.