检查对象是否是Swift中的给定类型

Enc*_*PTL 251 type-inference typechecking swift

我有一个由数组组成的数组AnyObject.我想迭代它,并找到所有元素作为数组实例.

如何在Swift中检查对象是否属于给定类型?

dre*_*wag 284

如果要检查特定类型,可以执行以下操作:

if let stringArray = obj as? [String] {
    // obj is a string array. Do something with stringArray
}
else {
    // obj is not a string array
}
Run Code Online (Sandbox Code Playgroud)

你可以使用"as!" 如果obj不是类型,那将抛出运行时错误[String]

let stringArray = obj as! [String]
Run Code Online (Sandbox Code Playgroud)

您还可以一次检查一个元素:

let items : [Any] = ["Hello", "World"]
for obj in items {
   if let str = obj as? String {
      // obj is a String. Do something with str
   }
   else {
      // obj is not a String
   }
}
Run Code Online (Sandbox Code Playgroud)


mea*_*ers 185

Swift 2.2 - 4.0.3中,您现在可以:

if object is String
{
}
Run Code Online (Sandbox Code Playgroud)

然后过滤你的数组:

let filteredArray = originalArray.filter({ $0 is Array })
Run Code Online (Sandbox Code Playgroud)


GoZ*_*ner 149

如果您只想知道某个对象是否是给定类型的子类型,那么有一种更简单的方法:

class Shape {}
class Circle : Shape {}
class Rectangle : Shape {}

func area (shape: Shape) -> Double {
  if shape is Circle { ... }
  else if shape is Rectangle { ... }
}
Run Code Online (Sandbox Code Playgroud)

"使用类型检查运算符(是)检查实例是否属于某个子类类型.如果实例属于该子类类型,则类型检查运算符返回true,否则返回false."摘录自:Apple Inc."Swift编程语言." iBooks.

在上文中,"某个子类型"的短语很重要.使用is Circleis Rectangle由编译器,因为该值接受shape被声明为Shape(类的超类CircleRectangle).

如果您使用的是原始类型,那么超类就是Any.这是一个例子:

 21> func test (obj:Any) -> String {
 22.     if obj is Int { return "Int" }
 23.     else if obj is String { return "String" }
 24.     else { return "Any" }
 25. } 
 ...  
 30> test (1)
$R16: String = "Int"
 31> test ("abc")
$R17: String = "String"
 32> test (nil)
$R18: String = "Any"
Run Code Online (Sandbox Code Playgroud)

  • 如果我将一个原始类型存储在一个数组中,或者如果该数组是一个原始类型,那么```仍然可以在这里工作?谢谢. (2认同)

Esq*_*uth 20

我有两种方法:

if let thisShape = aShape as? Square 
Run Code Online (Sandbox Code Playgroud)

要么:

aShape.isKindOfClass(Square)
Run Code Online (Sandbox Code Playgroud)

这是一个详细的例子:

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")
}
Run Code Online (Sandbox Code Playgroud)

编辑:3现在:

let myShape = Shape()
if myShape is Shape {
    print("yes it is")
}
Run Code Online (Sandbox Code Playgroud)

  • `isKindOfClass` 是 `NSObject` 协议的一个方法;它应该只适用于采用它的类(所有从 NSObject 派生的类,以及显式采用它的任何自定义 Swift 类) (2认同)

Ahm*_*eeb 14

对于swift4:

if obj is MyClass{
    // then object type is MyClass Type
}
Run Code Online (Sandbox Code Playgroud)


emm*_*phd 9

假设drawTriangle是UIView的一个实例.要检查drawTriangle是否为UITableView类型:

Swift 3中,

if drawTriangle is UITableView{
    // in deed drawTriangle is UIView
    // do something here...
} else{
    // do something here...
}
Run Code Online (Sandbox Code Playgroud)

这也可以用于您自己定义的类.您可以使用它来检查视图的子视图.


Fra*_*kel 7

只是为了基于已接受的答案和其他一些答案的完整性:

let items : [Any] = ["Hello", "World", 1]

for obj in items where obj is String {
   // obj is a String. Do something with str
}
Run Code Online (Sandbox Code Playgroud)

但你也可以(compactMap也“映射”不存在的值filter):

items.compactMap { $0 as? String }.forEach{ /* do something with $0 */ ) }
Run Code Online (Sandbox Code Playgroud)

以及使用的版本switch

for obj in items {
    switch (obj) {
        case is Int:
           // it's an integer
        case let stringObj as String:
           // you can do something with stringObj which is a String
        default:
           print("\(type(of: obj))") // get the type
    }
}
Run Code Online (Sandbox Code Playgroud)

但坚持这个问题,检查它是否是一个数组(即[String]):

let items : [Any] = ["Hello", "World", 1, ["Hello", "World", "of", "Arrays"]]

for obj in items {
  if let stringArray = obj as? [String] {
    print("\(stringArray)")
  }
}
Run Code Online (Sandbox Code Playgroud)

或者更一般地说(请参阅另一个问题的答案):

for obj in items {
  if obj is [Any] {
    print("is [Any]")
  }

  if obj is [AnyObject] {
    print("is [AnyObject]")
  }

  if obj is NSArray {
    print("is NSArray")
  }
}
Run Code Online (Sandbox Code Playgroud)


Mec*_*cki 6

as?并不总是会给您预期的结果,因为as不会测试数据类型是否属于特定类型,而是仅测试数据类型是否可以转换为表示为特定类型。

例如考虑以下代码:

func handleError ( error: Error ) {
    if let nsError = error as? NSError {
Run Code Online (Sandbox Code Playgroud)

每个符合Error协议的数据类型都可以转换为NSError对象,因此这总是会成功。但这并不意味着它error实际上是一个NSError对象或其子类。

正确的类型检查是:

func handleError ( error: Error ) {
    if type(of: error) == NSError.self {
Run Code Online (Sandbox Code Playgroud)

但是,这仅检查确切的类型。如果您还想包含 的子类NSError,您应该使用:

func handleError ( error: Error ) {
    if error is NSError.Type {
Run Code Online (Sandbox Code Playgroud)


Pat*_*erg 5

为什么不使用专门为此任务构建的内置功能?

let myArray: [Any] = ["easy", "as", "that"]
let type = type(of: myArray)

Result: "Array<Any>"
Run Code Online (Sandbox Code Playgroud)


ton*_*nCD 5

请注意这一点:

var string = "Hello" as NSString
var obj1:AnyObject = string
var obj2:NSObject = string

print(obj1 is NSString)
print(obj2 is NSString)
print(obj1 is String)
print(obj2 is String) 
Run Code Online (Sandbox Code Playgroud)

最后四行都返回 true,这是因为如果你输入

var r1:CGRect = CGRect()
print(r1 is String)
Run Code Online (Sandbox Code Playgroud)

...它当然打印“false”,但是警告说从 CGRect 到 String 的 Cast 失败。所以某些类型被桥接,“is”关键字调用隐式转换。

您最好使用以下其中一种:

myObject.isKind(of: MyClass.self)) 
myObject.isMember(of: MyClass.self))
Run Code Online (Sandbox Code Playgroud)