Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何确定对象的类型(在Swift中)?_Ios_Swift_Typechecking - Fatal编程技术网

Ios 如何确定对象的类型(在Swift中)?

Ios 如何确定对象的类型(在Swift中)?,ios,swift,typechecking,Ios,Swift,Typechecking,当试图理解一个程序时,或者在某些情况下,找出某个东西是什么类型是很有用的。我知道调试器可以向您显示一些类型信息,您通常可以依靠类型推断来避免在这些情况下不指定类型,但我还是希望有类似Python的type() dynamicType(请参阅) 更新:这在最新版本的Swift中已被更改,obj.dynamicType现在为您提供对该类型的引用,而不是动态类型的实例 这一款似乎是最有希望的,但到目前为止我还没有找到真正的类型 class MyClass { var count = 0 }

当试图理解一个程序时,或者在某些情况下,找出某个东西是什么类型是很有用的。我知道调试器可以向您显示一些类型信息,您通常可以依靠类型推断来避免在这些情况下不指定类型,但我还是希望有类似Python的
type()

dynamicType(请参阅) 更新:这在最新版本的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()
然而,这仅仅是实际发现任何给定对象类型的一小步


编辑:我已经删除了大量现在不相关的细节-如果您感兴趣,请查看编辑历史:)

动态类型。printClassName代码来自Swift手册中的一个示例。据我所知,无法直接获取自定义类名,但您可以使用
is
关键字检查实例类型,如下所示。如果您确实希望类名为字符串,此示例还显示了如何实现自定义类名函数

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
的子类已经实现了自己的类名函数。如果您正在使用Cocoa,则可以使用此属性

class MyObj: NSObject {
    init() {
        super.init()
        println("My class is \(self.className)")
    }
}
MyObj()

从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))
var unknownTypeVariable = …

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

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

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))
var unknownTypeVariable = …

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

以下是我推荐的两种方法:

if let thisShape = aShape as? Square 
或:

下面是一个详细的示例:

class Shape { }
class Square: Shape { } 
class Circle: Shape { }

var aShape = Shape()
aShape = Square()

if let thisShape = aShape as? Square {
    println("Its a square")
} else {
    println("Its not a square")
}

if aShape.isKindOfClass(Square) {
    println("Its a square")
} else {
    println("Its not a square")
}

Swift 2.0:

type(of: yourObject)
if unknownType is MyClass {
   //unknownType is of class type MyClass
}
进行这种类型的内省的正确方法是

然后,要从
Mirror
结构访问类型本身,可以使用属性
subjectType
如下所示:

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

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

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

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

取决于用例。但是让我们假设您想对“变量”类型做一些有用的事情。Swift
switch
语句非常强大,可以帮助您获得所需的结果

    let dd2 = ["x" : 9, "y" : "home9"]
    let dds = dd2.filter {
        let eIndex = "x"
        let eValue:Any = 9
        var r = false

        switch eValue {
        case let testString as String:
            r = $1 == testString
        case let testUInt as UInt:
            r = $1 == testUInt
        case let testInt as Int:
            r = $1 == testInt
        default:
            r = false
        }

        return r && $0 == eIndex
    }
在本例中,使用一个简单的字典,其中包含可以是UInt、Int或String的键/值对。在字典上的
.filter()
方法中,我需要确保正确测试值,并且只测试字符串(当它是字符串时)等。switch语句使这变得简单而安全! 通过将9赋给Any类型的变量,可以执行Int的开关。尝试将其更改为:

   let eValue:Any = "home9"
…然后再试一次。这一次,它将
作为字符串执行。

如果您收到“始终为真/失败”警告,则可能需要在使用
is
之前强制转换到任何一个

(foo as Any) is SomeClass

Swift 3版本:

type(of: yourObject)
if unknownType is MyClass {
   //unknownType is of class type MyClass
}

适用于Swift 3.0

String(describing: <Class-Name>.self)
字符串(描述:.self)
适用于Swift 2.0-2.3

String(<Class-Name>)
String()

Swift 3:

type(of: yourObject)
if unknownType is MyClass {
   //unknownType is of class type MyClass
}

如果将参数作为任意参数传递给函数,则可以在特殊类型上进行测试,如下所示:

   func isADate ( aValue : Any?) -> Bool{
        if (aValue as? Date) != nil {
            print ("a Date")
            return true
        }
        else {
            print ("This is not a date ")
            return false
        }
    }

老问题,但这符合我的需要(Swift 5.x):


评论:我不知道@Jérémylaponte如何回答这个问题。使用
type(of:)
只能通过检查编译时信息来工作,即使实际的类型是更具体的子类。现在有一种更简单的方法可以在Swift 5.1中动态查询类型,而无需像@Dash建议的那样求助于
dynamicType
。有关我从何处获得此信息的更多详细信息,请参阅


密码 Swift 5.1

// Within an instance method context
Self.self

// Within a static method context
self
这允许使用
Self
作为引用包含类型(在
struct
s、
enum
s和
final类
)或动态类型(在非
final
es的情况下)的缩写

解释 该提案很好地解释了为什么这种方法改进了
dynamicType

介绍
Self
解决了以下问题:

  • dynamicType
    仍然是Swift小写关键字规则的一个例外。这一变化消除了一个与实际情况不一致的特殊情况 斯威夫特的新标准。“自我”的意图更短、更清晰。信息技术 镜像引用当前实例的self
  • 它提供了一种更容易访问静态成员的方法。随着类型名变大,可读性受到影响。
    myExtremelyLarGetTypeName.staticMember
    难以键入和读取
  • 使用硬连线类型名称的代码的可移植性不如自动知道其类型的代码
  • 重命名类型意味着更新代码中的任何
    TypeName
    引用。使用
    self.dynamicType
    与斯威夫特的简洁和高效的目标格格不入 清晰之处在于它既嘈杂又深奥
  • 请注意,
    self.dynamicType.classMember
    TypeName.classMember
    在类类型中不能与非最终成员同义


    有趣的是,
    print(mc)
    dump(mc)
    将打印一个摘要(您可以从
    toString(mc)
    reflect(mc.summary)
    ),其中将包含类名。但不清楚如何自己获得类名。@David类似,但并非所有变量都是类实例。另外,这些问题实际上是关于检查类型