37 votes

Swift 3 - Comment vérifier le type de classe d'un objet

Cette ligne de code fonctionnait avec Swift 2, mais elle est maintenant incorrecte dans Swift 3.

if gestureRecognizer.isMember(of: UITapGestureRecognizer) { }

Je reçois cette erreur : Nom de membre ou appel de constructeur attendu après le nom du type.

Quelle est la manière correcte d'utiliser isMember(of:) ?

1 votes

Quels correctifs le compilateur vous offre-t-il ? ;)

0 votes

Este if gestureRecognizer.isMember(of: UITapGestureRecognizer()) { } ce qui ne fonctionne pas.

0 votes

Cliquez sur l'octogone rouge, le compilateur vous montrera deux fix-its (l'un d'eux résout votre problème :) ).

138voto

XAleXOwnZX Points 159

Le plus souvent, vous voudrez non seulement vérifier le type, mais aussi effectuer un cast vers ce type. Dans ce cas, utilisez :

if let gestureRecognizer as? UITapGestureRecognizer { }
else { /* not a UITapGestureRecognizer */ }

Opérateurs de coulée rapide

Ces opérateurs sont uniquement disponibles en Swift, mais fonctionnent toujours lorsqu'il s'agit de types Objective C.

  • El as opérateur

    • El as effectue un cast lorsqu'il est connu au moment de la compilation que le cast réussit toujours, comme dans le cas de l'upcasting ou du bridging. L'upcasting vous permet d'utiliser une expression comme une instance du super-type de son type, sans utiliser de variable intermédiaire.

    • Il s'agit de l'opérateur le plus préférable à utiliser, lorsque cela est possible. Il garantit le succès, sans avoir à se soucier de déballer une option ou de risquer un crash.

  • El as? opérateur

    • El as? L'opérateur effectue un transfert conditionnel de l'expression vers le type spécifié. L'adresse as? L'opérateur renvoie une option du type spécifié. Au moment de l'exécution, si le cast réussit, la valeur de expression est enveloppée dans une option et retournée ; sinon, la valeur retournée est nil . Si l'on effectue un moulage vers le type est garantie d'échouer ou est garantie de réussir, une erreur de compilation est générée.

    • Il s'agit du deuxième opérateur à utiliser de préférence. Utilisez-le pour gérer en toute sécurité le cas où un opérateur de coulée ne peut pas être exécuté.

  • El as! opérateur

    • El as! L'opérateur effectue un cast forcé de l'expression vers le type spécifié. L'adresse as! renvoie une valeur de l'opérateur type et non un type optionnel. Si le cast échoue, une erreur d'exécution est générée. Le comportement de x as! T est le même que le comportement de (x as? T)! .

    • C'est l'opérateur le moins souhaitable à utiliser. Je vous déconseille fortement d'en abuser. Tentative de conversion d'une expression vers un type incompatible fait planter votre programme.


Vérification rapide des types

Si vous voulez simplement vérifier le type d'une expression, sans à ce type, alors vous pouvez utiliser ces approches. Elles ne sont disponibles qu'en Swift, mais fonctionnent toujours lorsqu'il s'agit de types Objective C.

  • El is opérateur

    • El is vérifie au moment de l'exécution si l'expression peut être convertie dans le type spécifié. Il retourne true si l'expression peut être convertie dans le type spécifié ; sinon, elle renvoie le résultat suivant false
    • Fonctionne sur tous les types de Swift, y compris les types Objective C.
    • L'équivalent en Swift de isKind(of:)
  • Utilisation de type(of:)

    • Contrairement à la is on peut l'utiliser pour vérifier le type exact, sans tenir compte des sous-classes.
    • Peut être utilisé comme : type(of: instance) == DesiredType.self
    • L'équivalent en Swift de isMember(of:)

Méthodes héritées (Objective C) pour vérifier les types

Ce sont toutes des méthodes sur NSObjectProtocol . Ils peuvent être utilisés dans le code Swift, mais ils ne s'appliquent qu'aux classes qui dérivent de NSObjectProtocol (telles que les sous-classes de NSObject ). Je vous déconseille de les utiliser, mais je les mentionne ici par souci d'exhaustivité.

  • 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
    • Pour éviter cela en Swift, utilisez is à la place.
  • isMember(of:)

    • Renvoie une valeur booléenne qui indique si le récepteur est une instance d'une classe donnée.
    • Pour éviter cela en Swift, utilisez type(of: instance) == DesiredType.self à la place.
  • conforms(to:)

    • Renvoie une valeur booléenne qui indique si le récepteur se conforme à un protocole donné.
    • Pour éviter cela en Swift, utilisez is à la place.

0 votes

Bien vu, je suis en train d'écrire une analyse des différentes techniques. Tiens-toi bien

0 votes

@Hamish Hah, je voulais dire isKind(of:) . En fait, je n'arrive pas à trouver l'équivalent en swift de isMember(of:) . J'aurais pensé que vous pourriez utiliser quelque chose comme : type(of: "") == String.self mais c'est invalide.

1 votes

Huh, bizarre. On dirait que la chaîne littérale perturbe le compilateur d'une manière ou d'une autre. type(of: String()) == String.self fonctionne bien. Cela fonctionne aussi si vous l'assignez d'abord... let f = type(of: ""); if f == String.self {}

20voto

deadbeef Points 3874

Il existe plusieurs façons de vérifier la classe d'un objet. La plupart du temps, vous voudrez utiliser l'une ou l'autre des méthodes suivantes is ou le as? opérateurs comme suit :

let gestureRecognizer: UIGestureRecognizer = UITapGestureRecognizer()

// Using the is operator
if gestureRecognizer is UITapGestureRecognizer {
    // You know that the object is an instance of UITapGestureRecognizer,
    // but the compiler will not let you use UITapGestureRecognizer specific
    // methods or properties on gestureRecognizer because the type of the
    // variable is still UIGestureRecognizer
    print("Here")
}

// Using the as? operator and optional binding
if let tapGestureRecognizer = gestureRecognizer as? UITapGestureRecognizer {
    // tapGestureRecognizer is the same object as gestureRecognizer and is
    // of type UITapGestureRecognizer, you can use UITapGestureRecognizer
    // specific methods or properties.
    print("Here")
}

// Using the type(of:) global function
if type(of: gestureRecognizer) == UITapGestureRecognizer.self {
    // gestureRecognizer is an instance of UITapGestureRecognizer, but not any
    // of its subclasses (if gestureRecognizer was an instance of a subclass of
    // UITapGestureRecognizer, the body of this if would not execute).
    // This kind of check is rarely usefull, be sure this is really what you
    // want to do before you use it.
    print("Here")
}

// Using the isKind(of:) method
if gestureRecognizer.isKind(of: UITapGestureRecognizer.self) {
    // Like for the is operator, you know that the object is an instance of
    // UITapGestureRecognizer (or any subclass of UITapGestureRecognizer).
    // This is the Objective-C version of the is operator and will only work
    // on classes that inherit from NSObject, don't use it in Swift.
    print("Here")
}

// Using the isMember(of:) method
if gestureRecognizer.isMember(of: UITapGestureRecognizer.self) {
    // gestureRecognizer is an instance of UITapGestureRecognizer, but not
    // any of its subclasses.
    // This is the Objective-C version of type(of:) and will only work on
    // classes that inherit from NSObject, don't use it in Swift.
    print("Here")
}

5voto

Josh Homann Points 7888

Vous devez maintenant utiliser .self pour faire référence au type de classe.

let a = UITapGestureRecognizer()
print (a.isMember(of: UIGestureRecognizer.self))

Il y a aussi :

print (a is UITapGestureRecognizer)

3voto

Zigglzworth Points 1524

Swift 3 :

if gestureRecognizer is UITapGestureRecognizer {
            //It's a tap
}

1 votes

Comment vérifier que ce n'est pas le cas

1 votes

@RakeshiOSDev il suffit de mettre la déclaration entre parenthèses précédée de " !" comme if !(gestureRecognizer is UITapGestureRecognizer)

1 votes

J'ai lu "C'est un piège", et j'ai été super triste en le relisant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X