问答中心分类: IOS你如何找出对象的类型(在 Swift 中)?
0
匿名用户 提问 18小时 前

当试图理解一个程序时,或者在某些极端情况下,找出某个东西是什么类型是很有用的。我知道调试器可以向您显示一些类型信息,并且您通常可以依靠类型推断来避免在这些情况下不指定类型,但是,我真的很想拥有类似 Python 的东西type()
动态类型(见这个问题)
更新:这在最新版本的 Swift 中已更改,obj.dynamicType现在为您提供对类型的引用,而不是动态类型的实例。
这个似乎最有希望,但到目前为止我还没有找到实际的类型。

class MyClass {
    var count = 0
}

let mc = MyClass()

# update: this now evaluates as true
mc.dynamicType === MyClass.self

我还尝试使用类引用来实例化一个新对象,它工作,但奇怪的是给了我一个错误,说我必须添加一个required初始化器:
作品:

class MyClass {
    var count = 0
    required init() {
    }
}

let myClass2 = MyClass.self
let mc2 = MyClass2()

仍然只有一小步才能真正发现任何给定对象的类型
编辑:我已经删除了大量现在不相关的细节 – 如果您有兴趣,请查看编辑历史 🙂

David Berry 回复 18小时 前

可能的重复如何在 Swift 中获取变量的类?

David Berry 回复 18小时 前

有趣的是,print(mc)或者dump(mc)将打印一个摘要(您可以从中获取toString(mc)或者reflect(mc).summary),它将在某处包含类名。但目前尚不清楚如何自己获取类名。

David Berry 回复 18小时 前

@David 类似,但并非所有变量都是类实例。此外,这些问题实际上是关于检查类型是否与程序员正在寻找的匹配,而我希望只是找出批发的类型

David Berry 回复 18小时 前

使用类型(属于:yourObjectReference)

13 Answers
0
Gudbergur 回答 18小时 前

斯威夫特 2.0:
进行这种类型自省的正确方法是使用镜像结构,

let stringObject:String = "testing"
    let stringArrayObject:[String] = ["one", "two"]
    let viewObject = UIView()
    let anyObject:Any = "testing"

    let stringMirror = Mirror(reflecting: stringObject)
    let stringArrayMirror = Mirror(reflecting: stringArrayObject)
    let viewMirror = Mirror(reflecting: viewObject)
    let anyMirror = Mirror(reflecting: anyObject)

然后从Mirror您将使用该属性的结构subjectType像这样:

// Prints "String"
    print(stringMirror.subjectType)

    // Prints "Array<String>"
    print(stringArrayMirror.subjectType)

    // Prints "UIView"
    print(viewMirror.subjectType)

    // Prints "String"
    print(anyMirror.subjectType)

然后你可以使用这样的东西:

if anyMirror.subjectType == String.self {
        print("anyObject is a string!")
    } else {
        print("anyObject is not a string!")
    }
Thomas Verbeek 回复 18小时 前

这很棒。请注意,如果被镜像的对象是可选类型,那么将其与非可选类型进行比较将失败。StringOptional(String)不一样。

Joseph 回复 18小时 前

正是我在寻找的东西,想知道对象的类型是什么

Chris Prince 回复 18小时 前

在这种情况下是否存在一种比较类型不失败在比较可选类型和非可选类型时?

Mubin Mall 回复 18小时 前

这就是我一直在寻找的。谢谢@Gudbergur。

David Villegas 回复 18小时 前

这很甜!但是,是的,您绝对应该为可选用例添加(即:let anyObject: Any? = &quot;testing&quot;),检查 nil -&gt; 如果不是 nil -&gt; 设为非可选 -&gt; 并继续正常回答此答案

0
Dash 回答 18小时 前

dynamicType.printClassName代码来自 Swift 书中的一个示例。我不知道直接获取自定义类名,但您可以使用is关键字如下图。这个例子还展示了如何实现一个自定义的 className 函数,如果你真的想要类名作为一个字符串。

class Shape {
    class func className() -> String {
        return "Shape"
    }
}

class Square: Shape {
    override class func className() -> String {
        return "Square"
    }
}

class Circle: Shape {
    override class func className() -> String {
        return "Circle"
    }
}

func getShape() -> Shape {
    return Square() // hardcoded for example
}

let newShape: Shape = getShape()
newShape is Square // true
newShape is Circle // false
newShape.dynamicType.className() // "Square"
newShape.dynamicType.className() == Square.className() // true

笔记:
那个子类NSObject已经实现了自己的 className 函数。如果你正在使用 Cocoa,你可以使用这个属性。

class MyObj: NSObject {
    init() {
        super.init()
        println("My class is \(self.className)")
    }
}
MyObj()
Jiaaro 回复 18小时 前

嘿,不知道什么时候改变了,但正如 Alex Pretzlav 指出的那样,行为已经改变了。

Raphael 回复 18小时 前

是的。从 Swift 3.0 开始,subjectType不再可用,并且dynamicType导致来自编译器的弃用消息。

0
Alex Pretzlav 回答 18小时 前

作为Xcode 6.0.1(至少,不确定他们何时添加它),您的原始示例现在有效:

class MyClass {
    var count = 0
}

let mc = MyClass()
mc.dynamicType === MyClass.self // returns `true`

更新:
要回答最初的问题,您实际上可以成功地将 Objective-C 运行时与普通 Swift 对象一起使用。
尝试以下操作:

import Foundation
class MyClass { }
class SubClass: MyClass { }

let mc = MyClass()
let m2 = SubClass()

// Both of these return .Some("__lldb_expr_35.SubClass"), which is the fully mangled class name from the playground
String.fromCString(class_getName(m2.dynamicType))
String.fromCString(object_getClassName(m2))
// Returns .Some("__lldb_expr_42.MyClass")
String.fromCString(object_getClassName(mc))
Jiaaro 回复 18小时 前

看起来他们将其更改为为您提供类型而不是实例。

Alex Pretzlav 回复 18小时 前

@Jiaaro,我用我认为您在原始问题中寻找的内容更新了我的答案

0
Valerii Lider 回答 18小时 前

如果您只需要检查变量是否属于 X 类型,或者它是否符合某些协议,那么您可以使用is, 或者as?如下所示:

var unknownTypeVariable = …

if unknownTypeVariable is <ClassName> {
    //the variable is of type <ClassName>
} else {
    //variable is not of type <ClassName>
}

这相当于isKindOfClass在 Obj-C 中。
这相当于conformsToProtocol, 或者isMemberOfClass

var unknownTypeVariable = …

if let myClass = unknownTypeVariable as? <ClassName or ProtocolName> {
    //unknownTypeVarible is of type <ClassName or ProtocolName>
} else {
    //unknownTypeVariable is not of type <ClassName or ProtocolName>
}
awolf 回复 18小时 前

你答案的第二部分是错误的。 'if let' 语句与as?条件转换的作用与isKindOfClass同样,如果它成功,也只是提供演员的结果。

awolf 回复 18小时 前

相当于isMemberOfClass是条件object.dynamicType == ClassName.self.

0
Peter 回答 18小时 前

斯威夫特 3:

if unknownType is MyClass {
   //unknownType is of class type MyClass
}
Nicolas Miari 回复 18小时 前

我认为is存在于斯威夫特 3…?