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