web-dev-qa-db-ja.com

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

上記の例では、変数 "soon"がImplicitlyUnwrappedOptional<NSDate>型、または少なくともNSDate!型であることを示す方法を探しています。

318
Matt Bridges

2016年9月に更新

Swift 3.0:type(of:)を使ってください。 type(of: someThing)dynamicTypeキーワードが削除されたため)

2015年10月に更新

以下の例を新しいSwift 2.0の構文に更新しました(例:printlnprintに置き換えられました、toString()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)")

どの出力:

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>

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は変数のマングル型名を持っていました。 Ewan Swickのブログエントリ はこれらの文字列を解読するのに役立ちます。

例えば_TtSiはSwiftの内部Int型を表します。

Mike Ashは同じトピックをカバーする素晴らしいブログエントリを持っています

357
Klaas

編集: 新しいtoString関数 がSwift 1.2(Xcode 6.3)で導入されました

.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

YourClass.selfyourObject.dynamicTypeを呼び出してみてください。

参照: https://devforums.Apple.com/thread/227425

45
akashivskyy

これはあなたが探しているものですか?

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

"__NSDate"を印刷します

_ update _ :これはBeta05の時点では動作しなくなったようです。

30
Haiku Oezu

スイフト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>"
30
Evgenii

私の現在の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.
23
Matt Hagen

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"
18
kiding

classNameStringを返す)を介してクラスにアクセスすることはできます。

クラスを取得するには、実際にはいくつかの方法があります。例えば、classForArchiverclassForCoderclassForKeyedArchiver(すべてAnyClass!を返す)などです。

プリミティブの型を取得することはできません(プリミティブはnot aクラスです)。

例:

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
17
Leandros

オブジェクトに関する情報を取得するには、reflectを使用できます。
オブジェクトクラスの名前の例:

 var classname = reflect(現在).summary 
16
Stan

私は運が良かった:

let className = NSStringFromClass(obj.dynamicType)
13
mxcl

Xcode 8 Swift 3.0の使用タイプ(of :)

let className = "\(type(of: instance))"
12
Hari Kunwar

Xcode 8では、Swift 3.0

ステップ:

1. Typeを取得します。

オプション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
10
user1046037

Swift 3.0では、dynamicTypeキーワードが削除されたため、type(of:)を使用できます。

8
BrunoSerrano

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()

出力は次のとおりです。

  • 辞書は辞書型です
  • 配列は配列型です
  • numIntはInt型です
  • numFloatはCGFloat型です
  • numDoubleはDouble型です
  • classOneのタイプ:ClassOne
  • classTwoのタイプ:ClassTwo
  • 現在のタイプは次のとおりです。
  • lblのタイプ:UILabel
7
mauricioconde

トップアンサーには、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'
5
Joshua Dance

私はここで他の答えのいくつかを試してみましたが、ミラージュは根底にあるオブジェクトが何であるかについて非常にあるようです。

しかし、次のようにして、オブジェクトの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を表示します。

4
James Jones

私はうまくいけば他の人のために働くかもしれないこの解決策を見つけました。値にアクセスするためのクラスメソッドを作成しました。これはNSObjectサブクラスでのみ機能することに注意してください。しかし、少なくとも清潔できちんとした解決策です。

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

Cocoa(CocoaTouchではなく)を使用するときは、NSObjectのサブクラスであるオブジェクトにclassNameプロパティを使用できます。

println(now.className)

このプロパティは、NSObjectのサブクラスではない通常のSwiftオブジェクトには使用できません(実際、SwiftにはルートIDやオブジェクトタイプはありません)。

class Person {
    var name: String?
}

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

CocoaTouchでは、現時点では与えられた変数の型の説明を文字列で取得する方法はありません。同様の機能は、CocoaまたはCocoaTouchのプリミティブ型にも存在しません。

Swift REPLはその型を含む値の概要を出力することができるので、将来このようなイントロスペクションの方法がAPIを通じて可能になるでしょう。

_ edit _ dump(object)がうまくいくようです。

4
Matt Bridges

Swift 1.2を搭載した最新のXCode 6.3では、これが私が見つけた唯一の方法です。

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

上記のKlassとKevin Ballardによる答えとコメントに基づいて、私は以下のようになります。

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"
3

私は自己開発クラスの解決策(またはあなたがアクセスできるものなど)を見つけました。

次の計算プロパティをオブジェクトクラス定義内に配置します。

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

これで、オブジェクトのクラス名を次のようにして呼び出すことができます。

myObject.className

これは正確にあなたのクラス定義があなたが望む名前のクラスのような正確にという名前のファイル内で作られることに注意してください。

これは 一般的に case 上記の答えはほとんどの場合それを行うべきですです。しかし、 some の特別な場合には、別の解決策を考え出す必要があるかもしれません。


クラス名クラス(ファイル)自体の中が必要な場合は、単に次の行を使用できます。

let className = __FILE__.lastPathComponent.stringByDeletingPathExtension

たぶん、この方法はそこの何人かの人々を助けます。

3
Dschee
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)")
3
Alex Burla

ベータ5以降のlldbでは、次のコマンドでオブジェクトのクラスを見ることができます。

fr v -d r shipDate

これは次のように出力されます。

(DBSalesOrderShipDate_DBSalesOrderShipDate_ *) shipDate = 0x7f859940

展開されたコマンドは次のようなものを意味します。

Frame Variable(フレーム変数を印刷する)-d run_target(動的型を展開する)

「フレーム変数」を使用して変数値を出力すると、コードが実行されないことが保証されます。

ここでの回答の多くは最新のSwift(執筆時点ではXcode 7.1.1)では機能しません。

情報を得るための現在の方法はMirrorを作成しそれを調べることです。クラス名の場合は、次のように単純です。

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

オブジェクトに関する追加情報もMirrorから取得できます。詳細は http://swiftdoc.org/v2.1/type/mirror/ を参照してください。

3
Joseph Lord

Swift version 4:

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

ありがとうジョシュアダンス

2
dengApro

任意の値の型の型名を表示する一般的な方法はないようです。他の人が指摘したように、 class インスタンスではvalue.classNameを印刷できますが、プリミティブな値では実行時に型情報が消えたように見えます。

たとえば、1.something()と入力してIntの任意の値に対してsomethingを取得する方法がないかのように見えます。 (別の回答として、i.bridgeToObjectiveC().classNameを使用してヒントを得ることもできますが、__NSCFNumbernot 実際にはiの型です。Objective-C関数の境界を越えたときに変換されるものですコール。)

私は間違っていることを証明できればうれしいですが、型チェックはすべてコンパイル時に行われ、C++(RTTIを無効にした状態)のように実行時に消えてしまいます。

2
ipmcc

これは、 object または Type の型文字列を取得する方法で、これは 一定の であり、オブジェクト定義が属する module のどちらに属するかを考慮します。 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
2
Igor Muzyka

スイフト4:

// "TypeName"
func stringType(of some: Any) -> String {
    let string = (some is Any.Type) ? String(describing: some) : String(describing: type(of: some))
    return string
}

// "ModuleName.TypeName"
func fullStringType(of some: Any) -> String {
    let string = (some is Any.Type) ? String(reflecting: some) : String(reflecting: type(of: some))
    return string
}

使用法:

print(stringType(of: SomeClass()))     // "SomeClass"
print(stringType(of: SomeClass.self))  // "SomeClass"
print(stringType(of: String()))        // "String"
print(fullStringType(of: String()))    // "Swift.String"
2
Desmond Hume

厳密にはあなたがしていることではありませんが、Swiftの型に対して変数の型をチェックすることもできます。

let object: AnyObject = 1

if object is Int {
}
else if object is String {
}

例えば。

1

Xcode 7.3.1、Swift 2.2:

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

1
leanne

Swift 3.0、Xcode 8

次のコードで、インスタンスにそのクラスを問い合わせることができます。また、2つのインスタンスを比較して、同じクラスにすることもできます。

// 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")
}
1
LukeSideWalker

タイプのオブジェクト または オブジェクトのクラス Swiftに取得するには、 タイプ(of:yourObject)を使用する必要があります

タイプ(of:yourObject)

1
Rahul Panzade

以下のコードスニペットを見て、あなたが以下のような何かを探しているかどうか私に知らせてください。

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

var nowDataType = Mirror(reflecting: now)
print("Now is of type: \(nowDataType.subjectType)")

var soonDataType = Mirror(reflecting: soon)
print("Soon is of type: \(soonDataType.subjectType)")
0
DILIP KOSURI

これは、オブジェクトがクラスの型かどうかを調べるときにも便利です。

if someObject is SomeClass {
    //someObject is a type of SomeClass
}
0
Nam

String(describing: 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表現に影響を与えるさまざまなレベルのアクセス制御を持っています。クラスがprivateまたはfileprivateアクセス制御レベルを持つ場合、Swiftは問題のクラスの "ネスト"クラスに関連するある種の識別子を追加するようです。

PrivateDemoSystemCallFileprivateDemoSystemCallの両方の結果は、両方とも同じ親クラスにネストされているため、同じ識別子が追加されます。

私はそれを取り除くための方法をまだ見つけていません。

たった2セントです。

0
Philipp Jahoda