web-dev-qa-db-fra.com

Vérifier si un objet est d'un type donné dans Swift

J'ai un tableau qui est composé de AnyObject. Je veux parcourir dessus et trouver tous les éléments qui sont des instances de tableau.

Comment puis-je vérifier si un objet est d'un type donné dans Swift?

241
Encore PTL

Si vous souhaitez vérifier un type spécifique, vous pouvez effectuer les opérations suivantes:

if let stringArray = obj as? [String] {
    // obj is a string array. Do something with stringArray
}
else {
    // obj is not a string array
}

Vous pouvez utiliser "comme!" et cela générera une erreur d'exécution si obj n'est pas de type [String]

let stringArray = obj as! [String]

Vous pouvez également vérifier un élément à la fois:

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
   }
}
274
drewag

Dans Swift 2.2 - 5 vous pouvez maintenant faire:

if object is String
{
}

Puis pour filtrer votre tableau:

let filteredArray = originalArray.filter({ $0 is Array })

Si vous avez plusieurs types à vérifier:

    switch object
    {
    case is String:
        ...

    case is OtherClass:
        ...

    default:
        ...
    }
171
meaning-matters

Si vous voulez seulement savoir si un objet est un sous-type d'un type donné, il existe une approche plus simple:

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

func area (shape: Shape) -> Double {
  if shape is Circle { ... }
  else if shape is Rectangle { ... }
}

“Utilisez l'opérateur de vérification de type (is) pour vérifier si une instance est d'un certain type de sous-classe. L'opérateur de vérification de type renvoie true si l'instance est de ce type de sous-classe et false si ce n'est pas le cas. "Extrait de: Apple Inc." Le langage de programmation Swift. " iBooks .

Dans ce qui précède, la phrase "d'un certain type de sous-classe" est importante. L'utilisation de is Circle et is Rectangle est acceptée par le compilateur car cette valeur shape est déclarée comme Shape (une super-classe de Circle et Rectangle. ).

Si vous utilisez des types primitifs, la superclasse serait Any. Voici un exemple:

 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"
149
GoZoner

J'ai 2 façons de le faire:

if let thisShape = aShape as? Square 

Ou:

aShape.isKindOfClass(Square)

Voici un exemple détaillé:

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")
}

Edit: 3 maintenant:

let myShape = Shape()
if myShape is Shape {
    print("yes it is")
}
20
Esqarrouth

pour Swift4:

if obj is MyClass{
    // then object type is MyClass Type
}
14
Ahmad Labeeb

Supposons que drawTriangle est une instance de UIView.Pour vérifier si drawTriangle est de type UITableView:

Dans Swift,

if drawTriangle is UITableView{
    // in deed drawTriangle is UIView
    // do something here...
} else{
    // do something here...
}

Cela pourrait également être utilisé pour les classes définies par vous-même. Vous pouvez utiliser ceci pour vérifier les sous-vues d'une vue.

9
emmmphd

Pourquoi ne pas utiliser la fonctionnalité intégrée spécialement conçue pour cette tâche?

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

Result: "Array<Any>"
4
Patrik Forsberg

Soyez averti à ce sujet:

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) 

Les quatre dernières lignes renvoient true, car si vous tapez

var r1:CGRect = CGRect()
print(r1 is String)

... il affiche "faux" bien sûr, mais un avertissement indique que la conversion de CGRect en chaîne échoue. Ainsi, certains types sont pontés et le mot clé 'is' appelle une distribution implicite.

Vous devriez mieux utiliser l'un de ceux-ci:

myObject.isKind(of: MyClass.self)) 
myObject.isMember(of: MyClass.self))
4
tontonCD

Si vous voulez juste vérifier la classe sans recevoir d'avertissement à cause de la valeur définie non utilisée (let someVariable ...), vous pouvez simplement remplacer le laisser laisser par un booléen:

if (yourObject as? ClassToCompareWith) != nil {
   // do what you have to do
}
else {
   // do something else
}

Xcode a proposé cela lorsque j'ai utilisé la méthode let sans utiliser la valeur définie.

2
the_mariooo

Pourquoi ne pas utiliser quelque chose comme ça

fileprivate enum types {
    case typeString
    case typeInt
    case typeDouble
    case typeUnknown
}

fileprivate func typeOfAny(variable: Any) -> types {
    if variable is String {return types.typeString}
    if variable is Int {return types.typeInt}
    if variable is Double {return types.typeDouble}
    return types.typeUnknown
}

dans Swift 3.

2
Dawy

Swift 3:

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

if aShape.isKind(of: Circle.self) {
}
1
Harris

myObject as? String renvoie nil si myObject n'est pas un String. Sinon, il retourne un String? afin que vous puissiez accéder à la chaîne elle-même avec myObject! ou la lancer avec myObject! as String en toute sécurité.

1
cprcrack

Juste pour être complet, basé sur la réponse acceptée et quelques autres:

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

for obj in items where obj is String {
   // obj is a String. Do something with str
}

Mais vous pouvez aussi (compactMap aussi "mapper" les valeurs que filter ne fait pas):

items.compactMap { $0 as? String }.forEach{ /* do something with $0 */ ) }

Et une version utilisant 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
    }
}

Mais s’en tenir à la question, pour vérifier s’il s’agit d’un tableau (c'est-à-dire [String]):

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

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

Ou plus généralement (voir cette autre question répond ):

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")
  }
}
0
FranMowinckel

Si vous ne savez pas que vous obtiendrez un tableau de dictionnaires ou un dictionnaire unique dans la réponse du serveur, vous devez vérifier si le résultat contient un tableau ou non.
Dans mon cas, je reçois toujours un tableau de dictionnaires sauf une fois. Donc, pour gérer cela, j’ai utilisé le code ci-dessous pour Swift 3.

if let str = strDict["item"] as? Array<Any>

Ici comme? Array vérifie si la valeur obtenue est un tableau (d'éléments du dictionnaire). Sinon, vous pouvez gérer s'il s'agit d'un élément de dictionnaire unique qui n'est pas conservé dans un tableau.

0
V.S

Swift 4.2, Dans mon cas, en utilisant la fonction isKind.

isKind (of :) Renvoie une valeur booléenne indiquant si le destinataire est une instance d'une classe donnée ou une instance d'une classe quelconque qui hérite de cette classe.

  let items : [AnyObject] = ["A", "B" , ... ]
  for obj in items {
    if(obj.isKind(of: NSString.self)){
      print("String")
    }
  }

Readmore https://developer.Apple.com/documentation/objectivec/nsobjectprotocol/1418511-iskind

0
Tung Tran

Si vous avez une réponse comme celle-ci:

{
  "registeration_method": "email",
  "is_stucked": true,
  "individual": {
    "id": 24099,
    "first_name": "ahmad",
    "last_name": "zozoz",
    "email": null,
    "mobile_number": null,
    "confirmed": false,
    "avatar": "http://abc-abc-xyz.amazonaws.com/images/placeholder-profile.png",
    "doctor_request_status": 0
  },
  "max_number_of_confirmation_trials": 4,
  "max_number_of_invalid_confirmation_trials": 12
}

et vous voulez vérifier la valeur is_stucked qui sera lue comme AnyObject, tout ce que vous avez à faire est ceci

if let isStucked = response["is_stucked"] as? Bool{
  if isStucked{
      print("is Stucked")
  }
  else{
      print("Not Stucked")
 }
}
0
Abo3atef