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?
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
}
}
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:
...
}
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"
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")
}
pour Swift4:
if obj is MyClass{
// then object type is MyClass Type
}
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.
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>"
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))
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.
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.
Swift 3:
class Shape {}
class Circle : Shape {}
class Rectangle : Shape {}
if aShape.isKind(of: Circle.self) {
}
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é.
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")
}
}
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.
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
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")
}
}