J'ai un tableau composé de AnyObject
. Je veux le parcourir 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?
J'ai un tableau composé de AnyObject
. Je veux le parcourir 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?
Réponses:
Si vous souhaitez vérifier par rapport à un type spécifique, vous pouvez procéder comme suit:
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 "as!" et cela générera une erreur d'exécution s'il 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
}
}
?
n'est pas présent. On dirait as
et ?
lorsqu'il est combiné sera effectuer une vérification de l' exécution. Quand serait-il approprié de l'utiliser as
sans ?
? Merci d'avance.
as
sans le ?
s'il n'y a aucun moyen que votre programme puisse récupérer de l'objet n'étant pas de ce type car le programme s'arrêtera immédiatement s'il ne l'est pas. L'utilisation de ?
dans l' if
instruction permet au programme de continuer.
?
dans ce cas effectuerait une vérification de type "générique", si oui, à la clause if, sinon, à la clause else. Sans le ?
reste, il ne serait jamais entré et, comme vous l'avez souligné, provoquait une erreur d'exécution. Merci encore.
?
permet à l'affectation de retourner, nil
provoquant le retour de l'instruction if false
et donc de passer à l'instruction else. Cependant, je pense que cette explication aide à la compréhension, mais if let
c'est en fait un cas spécial dans le compilateur
Dans Swift 2.2 - 5, vous pouvez désormais:
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:
...
}
object
comme un String
à l'intérieur des accolades (au moins dans Swift 2), tandis qu'avec la let
solution, vous pouvez le faire.
object
dans le bloc est très bien.
object.uppercaseString
car le type de la variable n'est pas converti en ce type, vous venez de vérifier que l'objet (pointé par la variable) est unString
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 appartient à ce type de sous-classe et false dans le cas contraire. » Extrait de: Apple Inc. «The Swift Programming Language». iBooks .
Dans ce qui précède, l'expression «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 superclasse 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"
is
toujours ici? Merci.
object
as Any
. Mis à jour avec un exemple.
AnyObject
est suggéré, semble avoir été répliqué en raison de AnyObject
ne pas hériter de NSObject
. Si Any
c'est différent, ce serait en fait une excellente solution également. Merci.
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")
}
Modifier: 3 maintenant:
let myShape = Shape()
if myShape is Shape {
print("yes it is")
}
isKindOfClass
est une méthode du NSObject
protocole; il ne devrait fonctionner que pour les classes qui l'adoptent (toutes les classes descendant de NSObject, plus toute classe Swift personnalisée qui l'adopte explicitement)
pour swift4:
if obj is MyClass{
// then object type is MyClass Type
}
Supposons drawTriangle est une instance de UIView. Pour vérifier si drawTriangle est de type UITableView:
Dans Swift 3 ,
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 l'utiliser 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, c'est parce que 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. Certains types sont donc pontés, et le mot-clé 'is' appelle un transtypage implicite.
Vous devriez mieux utiliser l'un d'eux:
myObject.isKind(of: MyClass.self))
myObject.isMember(of: MyClass.self))
Si vous voulez simplement vérifier la classe sans recevoir d'avertissement à cause de la valeur définie inutilisée (let someVariable ...), vous pouvez simplement remplacer le let stuff par un booléen:
if (yourObject as? ClassToCompareWith) != nil {
// do what you have to do
}
else {
// do something else
}
Xcode l'a proposé lorsque j'ai utilisé la méthode let et que je n'ai pas utilisé 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 4.2, dans mon cas, en utilisant la fonction isKind.
isKind (of :) Renvoie une valeur booléenne qui indique si le récepteur est une instance de la classe donnée ou une instance de toute classe qui hérite de cette classe.
let items : [AnyObject] = ["A", "B" , ... ]
for obj in items {
if(obj.isKind(of: NSString.self)){
print("String")
}
}
En savoir plus https://developer.apple.com/documentation/objectivec/nsobjectprotocol/1418511-iskind
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 qui filter
ne le font 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 en restant sur la question, pour vérifier s'il s'agit d'un tableau (ie [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éponse ):
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")
}
}
as?
ne vous donnera pas toujours le résultat attendu, car as
il ne teste pas si un type de données est d'un type spécifique, mais uniquement si un type de données peut être converti ou représenté comme un type spécifique.
Considérez ce code par exemple:
func handleError ( error: Error ) {
if let nsError = error as? NSError {
Chaque type de données conforme au Error
protocole peut être converti en NSError
objet, cela réussira donc toujours . Pourtant, cela ne signifie pas qu'il error
s'agit en fait d'un NSError
objet ou d'une sous-classe de celui-ci.
Une vérification de type correcte serait:
func handleError ( error: Error ) {
if type(of: error) == NSError.self {
Cependant, cela vérifie uniquement le type exact. Si vous souhaitez également inclure la sous-classe de NSError
, vous devez utiliser:
func handleError ( error: Error ) {
if error is NSError.Type {
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")
}
}
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 éventail 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 de dictionnaire). Dans les autres cas, vous pouvez gérer s'il s'agit d'un élément de dictionnaire unique qui n'est pas conservé dans un tableau.
Version Swift 5.2 et Xcode: 11.3.1 (11C504)
Voici ma solution de vérification du type de données:
if let typeCheck = myResult as? [String : Any] {
print("It's Dictionary.")
} else {
print("It's not Dictionary.")
}
J'espère que cela vous aidera.