Obtenir le nom de classe d'un objet en Swift : performances et bonnes pratiques

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Pourquoi un développeur Swift a-t-il besoin du nom de classe sous forme de chaîne ?

\n\n

Imaginez la situation : vous développez un système de logging pour une application complexe. Chaque événement doit contenir non seulement un message, mais aussi le nom de la classe dans laquelle il s'est produit. Ou vous construisez un parseur JSON universel qui doit déterminer le type de modèle à partir d'une clé textuelle. Ou encore, vous déboguez un retain cycle et souhaitez afficher dynamiquement tous les objets en mémoire avec leurs noms de classe.

\n\n

Dans tous ces cas, vous avez besoin de la même chose : obtenir le nom de classe d'un objet en Swift sous forme de chaîne. Cela semble simple, non ? Mais ce n'est pas si évident. Contrairement à Objective-C, Swift n'a pas de méthode "magique" unique qui fonctionne parfaitement dans toutes les situations. De plus, différentes approches offrent des performances variables, et certaines produisent des résultats inattendus.

\n\n

Dans cet article, nous ne nous contenterons pas de vous donner une réponse toute faite. Nous allons passer en revue toutes les méthodes pour obtenir le class name en Swift, comparer leur vitesse et vous montrer quand utiliser chaque approche. Vous apprendrez à éviter les pièges courants et à écrire un code fiable pour la production.

\n\n

La méthode classique : String(describing: type(of:))

\n\n

La réponse la plus populaire sur Stack Overflow pour ce sujet est d'utiliser la combinaison de type(of:) et String(describing:). Voyons comment cela fonctionne.

\n\n
class Voiture {\n    var modele: String\n    init(modele: String) {\n        self.modele = modele\n    }\n}\n\nlet maVoiture = Voiture(modele: "Tesla Model 3")\nlet nomClasse = String(describing: type(of: maVoiture))\nprint(nomClasse) // "Voiture"
\n\n

Cette méthode est simple et intuitive. type(of:) retourne le métatype de l'objet, et String(describing:) le convertit en chaîne. Mais attention : elle ne fonctionne pas correctement avec les types optionnels et les protocoles.

\n\n

Le problème avec les optionnels

\n\n
let voitureOptionnelle: Voiture? = Voiture(modele: "BMW")\nlet nomOptionnel = String(describing: type(of: voitureOptionnelle))\nprint(nomOptionnel) // "Optional<Voiture>" — pas ce que vous attendiez !
\n\n

Au lieu de "Voiture", vous obtenez "Optional<Voiture>". Cela se produit car type(of:) retourne le type de la valeur elle-même, pas de son contenu. Pour un optionnel, c'est Optional<Voiture>.

\n\n

Le problème avec les protocoles et l'héritage

\n\n
protocol Conductible { }\nextension Voiture: Conductible { }\n\nlet objetConductible: Conductible = Voiture(modele: "Audi")\nlet nomProtocole = String(describing: type(of: objetConductible))\nprint(nomProtocole) // "Voiture" — chanceux ici, mais pas toujours
\n\n

Avec les protocoles, le résultat peut être imprévisible, surtout avec la composition de protocoles ou Any. Conclusion : cette méthode est adaptée aux cas simples, mais pas pour du code de production avec des optionnels et des types complexes.

\n\n

L'héritage Objective-C : NSStringFromClass

\n\n

Si vous venez d'Objective-C, vous vous souvenez sûrement de NSStringFromClass([self class]). En Swift, cela fonctionne aussi, mais avec des réserves :

\n\n
import Foundation\n\nclass Moto {\n    var marque: String\n    init(marque: String) {\n        self.marque = marque\n    }\n}\n\nlet maMoto = Moto(marque: "Harley")\nlet nomObjC = NSStringFromClass(type(of: maMoto))\nprint(nomObjC) // "_TtC11YourModule11Moto" — un nom "mangled" !
\n\n

En Swift, les classes ont des noms "mangled" (altérés). Au lieu de "Moto", vous obtenez quelque chose comme _TtC11YourModule11Moto. Pour obtenir un nom propre, vous devez le "démangler" manuellement ou utiliser String(describing:).

\n\n

Cependant, il y a un avantage important : NSStringFromClass fonctionne avec tous les objets, y compris les optionnels, et ne plante pas sur nil. Mais pour la clarté du code, il est préférable de ne pas l'utiliser directement.

\n\n

Quand NSStringFromClass est-il vraiment nécessaire ?

\n
    \n
  • Lorsque vous travaillez avec l'Objective-C

Blogs

Book Recommendations