Method Swizzling dans le développement iOS et Android : concepts clés, techniques et principe de fonctionnement

Auteur : IT Sectr Publié le : 2026-05-17 Temps de lecture : 9 min

Method Swizzling est une technique d'exécution où les implémentations de deux méthodes de classe sont échangées pendant l'exécution. Elle permet de redéfinir ou de compléter le comportement d'une méthode système sans créer de sous-classe ni modifier le code source. La technique a trouvé sa plus grande application dans le développement iOS avec Objective-C, mais des analogues existent en Kotlin/Android via la réflexion. Selon NSHipster Guide by Mattt, 2024, le swizzling est l'un des mécanismes les plus puissants, mais aussi les plus dangereux de l'Objective-C Runtime.

Points essentiels

  • Method Swizzling — échange d'implémentations de deux méthodes Objective-C à l'exécution via sel_registerName et method_exchangeImplementations.
  • Objective-C Runtime permet le swizzling grâce à la répartition dynamique via objc_msgSend et la table de répartition.
  • Swizzling sur Android est implémenté via Java Reflection avec remplacement d'implementation dans les fichiers dex ou via l'API Gradle Transform.
  • Risques du swizzling — conflits entre bibliothèques, incompatibilité avec les mises à jour iOS, crash lors du changement de signatures de méthodes.
  • Swizzling sécurisé nécessite dispatch_once, atomicité et appel de l'implémentation originale à l'intérieur de la méthode swizzlée.

Qu'est-ce que le Method Swizzling ?

Method Swizzling est une technique d'exécution qui échange les implémentations de deux méthodes Objective-C. Après le swizzling, l'appel de originalSelector exécute le code de swizzledSelector, et vice versa. Ceci est possible grâce à l'architecture de l'Objective-C Runtime, où chaque sélecteur (SEL) est associé à une implémentation (IMP) via une table de répartition — une table qui peut être modifiée pendant l'exécution.

Le terme «swizzling» a été introduit dans la communauté des développeurs Cocoa au début des années 2000. La technique a acquis une large reconnaissance grâce à des bibliothèques telles que : AFNetworking (swizzling de UIWebView pour suivre le chargement), Aspects (framework AOP basé sur le swizzling) et FLEX (outil de débogage qui swizzle les méthodes système pour inspection). Aujourd'hui, le swizzling est utilisé implicitement dans la plupart des applications iOS — via des bibliothèques de surveillance et d'analyse.

Une propriété importante du swizzling est la globalité : le remplacement d'implémentation se produit au niveau de la classe, pas de l'instance. Si une bibliothèque swizzle la méthode UIViewController.viewDidLoad, cela affecte TOUTES les instances d'UIViewController dans l'application, y compris celles du système. C'est à la fois la force du swizzling — une ligne de code change le comportement de toute l'application — et la principale source de bugs.

Comment fonctionne le Method Swizzling en Objective-C

Objective-C Runtime stocke dans chaque classe une table de répartition — un dictionnaire dont la clé est SEL (identifiant de méthode) et la valeur est IMP (pointeur vers la fonction d'implémentation). Lorsqu'une application envoie un message à un objet, objc_msgSend effectue une recherche linéaire dans cette table. Le Method Swizzling remplace l'IMP d'un SEL par l'IMP d'un autre SEL, redirigeant les appels.

objective-c
// Implémentation sécurisée du method swizzling
@implementation NSObject (SafeSwizzle)

+ (void)swizzleClassMethod:(SEL)original
                  with:(SEL)swizzled {
    Class cls = [self class];
    SEL originalSel = original;
    SEL swizzledSel = swizzled;

    Method originalMethod = class_getInstanceMethod(cls, originalSel);
    Method swizzledMethod = class_getInstanceMethod(cls, swizzledSel);

    method_exchangeImplementations(originalMethod, swizzledMethod);
}

@end

La fonction clé est method_exchangeImplementations(Method, Method). Elle échange atomiquement les IMPs de deux objets Method. Après l'appel, la table de répartition de la classe est modifiée : appeler original exécute le code swizzlé, appeler swizzlé exécute le code original. La catégorie SafeSwizzle ajoute cette méthode à tous les NSObject, permettant à n'importe quelle classe d'effectuer un swizzling.

Une implémentation sécurisée du swizzling nécessite d'appeler l'implémentation originale à l'intérieur de la version swizzlée. Sinon, le comportement original de la méthode est perdu irréversiblement. Le motif correct est de sauvegarder l'IMP original avant l'échange et de l'appeler dans la méthode swizzlée :

objective-c
// Swizzling avec appel de l'implémentation originale
- (void)swizzled_viewDidLoad {
    // 1. Appel de l'implémentation originale
    [self swizzled_viewDidLoad];

    // 2. Logique supplémentaire après l'appel original
    NSLog("viewDidLoad exécuté, swizzling actif");
}

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self swizzleClassMethod:@selector(viewDidLoad)
                            with:@selector(swizzled_viewDidLoad)];
    });
}

dispatch_once garantit que le swizzling s'exécute exactement une fois pendant la durée de vie de l'application. Swizzler à nouveau la même méthode entraînerait une récursion infinie : la méthode swizzlée s'appellerait elle-même. +load est appelé lorsque la classe est chargée dans le runtime — c'est un point sûr pour le swizzling qui s'exécute avant le code principal de l'application.

Anatomie de la table de répartition

La table de répartition d'une classe Objective-C est un tableau de structures method_t contenant SEL, IMP et le type de retour. method_exchangeImplementations échange simplement deux pointeurs IMP dans cette table. Important : le swizzling fonctionne uniquement au niveau de la classe, pas au niveau du protocole. Si une méthode est définie dans un protocole mais non implémentée, la table de répartition ne contient pas d'entrée pour le swizzling.

Impact du swizzling sur les performances

Le surcoût du swizzling est minime — l'échange de deux pointeurs IMP dans la table de répartition prend quelques nanosecondes. Après le swizzling, l'appel de méthode n'est pas ralenti : objc_msgSend trouve l'IMP dans le même temps O(1) qu'avant le swizzling. La seule opération supplémentaire est une vérification du cache de méthodes lors du premier appel après l'échange. Selon les données de l'Apple Performance Team, le swizzling n'affecte pas les performances de l'application.

Applications du Method Swizzling dans iOS

Method Swizzling est utilisé dans trois scénarios principaux : surveillance et analyse (suivi de viewDidLoad, viewDidAppear pour l'envoi automatique d'événements), interception AOP (journalisation des paramètres de tous les appels de méthode) et hotfix (correction d'un bug en production sans review App Store via des bibliothèques comme JSPatch).

  • Analyse automatique — swizzling de UIViewController.viewDidAppear pour envoyer des événements de vue d'écran sans dupliquer le code dans chaque contrôleur.
  • Journalisation des requêtes réseau — swizzling de NSURLSession.resume pour suivre toutes les requêtes HTTP, y compris celles des bibliothèques tierces.
  • AOP (Programmation Orientée Aspects) — la bibliothèque Aspects swizzle les méthodes et exécute un bloc de code avant/après/à la place de l'appel original.
  • Hotfix — remplacement de l'implémentation d'une méthode buguée par une version corrigée sans reconstruire l'application (interdit par l'App Review depuis 2020).
  • Tests et mocks — OCMock utilise le swizzling pour remplacer les méthodes par des implémentations mock dans les tests unitaires.

Chacun de ces scénarios fonctionne parce que le swizzling est appliqué centralisément. Une bibliothèque d'analyse effectue le swizzling une fois dans +load, et toutes les instances d'UIViewController dans l'application commencent à envoyer des événements. Le développeur n'a pas besoin d'ajouter du code dans chaque contrôleur — cela réduit la duplication et le risque d'erreurs.

Method Swizzling sur Android : réflexion et manipulation de bytecode

Sur Android, le method swizzling au sens classique d'Objective-C est impossible — Java/Kotlin utilisent une répartition statique via vtable. Cependant, il existe des mécanismes qui atteignent un effet similaire : Java Reflection pour remplacer les implémentations à l'exécution et l'API Gradle Transform / ASM pour modifier le bytecode au moment de la compilation.

kotlin
// Swizzling sur Android via réflexion + companion object
class Logger {
    companion object {
        var originalImpl: (() -> Unit)? = null
    }

    fun log() {
        println("log original")
    }
}

// Remplacement d'implémentation à l'exécution via réflexion
fun swizzleLog() {
    val originalMethod = Logger::class.java
        .getDeclaredMethod("log")
    originalMethod.isAccessible = true

    Logger.originalImpl = {
        originalMethod.invoke(Logger())
    }

    // Substitution via fonction inline
    println("swizzlé : log intercepté")
}

Ce code remplace le comportement de la méthode log() via Java Reflection : getDeclaredMethod accède à l'implémentation privée, isAccessible désactive les vérifications d'accès. Au lieu d'appeler directement log(), un wrapper est appelé qui exécute une logique supplémentaire. Cependant, Android optimise les méthodes chaudes via JIT — la réflexion peut ne pas fonctionner sur les segments AOT déjà compilés.

Une approche plus fiable est la manipulation de bytecode via l'API Gradle Transform ou AGP (Android Gradle Plugin) avec la bibliothèque ASM. La modification du bytecode est effectuée au moment de la compilation : ASM ajoute des appels à chaque méthode de la classe. C'est ainsi que fonctionnent les outils de couverture de code (JaCoCo) et de surveillance des performances (Firebase Performance Monitoring).

Risques et bonnes pratiques du Method Swizzling

Method Swizzling est une technique à haut risque. Conflits entre bibliothèques : si deux bibliothèques swizzlent la même méthode, l'ordre d'exécution n'est pas garanti. Incompatibilité avec les mises à jour iOS : si Apple modifie la signature ou supprime une méthode dans une nouvelle version d'iOS, le swizzling entraîne des crashes. Manque de visibilité dans le code : le swizzling n'est pas visible dans l'implémentation de la classe, ce qui complique le débogage.

RisqueDescriptionAtténuation
Conflit de bibliothèquesDeux bibliothèques swizzlent viewDidAppear — l'une casse l'autreVérifier si la méthode est déjà swizzlée via class_getInstanceMethod
RécursionSwizzler à nouveau la même méthode provoque une boucle infinieToujours utiliser dispatch_once
Changement de signatureApple modifie la signature de la méthode dans un nouvel iOS — IMP incompatibleTester sur toutes les versions iOS supportées
InvisibilitéLe swizzling n'apparaît pas dans la pile d'appels XcodeDocumenter toutes les opérations de swizzling dans le code
App ReviewApple rejette les applications avec du swizzling non documentéUtiliser uniquement des API publiques et documenter l'objectif

Les bonnes pratiques pour un swizzling sécurisé incluent : toujours appeler l'implémentation originale, effectuer le swizzling strictement dans +load via dispatch_once, nommer les méthodes swizzlées avec un préfixe (par exemple, s_originalMethodName), documenter chaque opération de swizzling avec son objectif. La bibliothèque Aspects résout le problème de conflit grâce à l'exécution en chaîne de blocs avant/après la méthode originale.

Alternatives au Method Swizzling dans le développement moderne

Les alternatives au method swizzling sont préférables pour le code de production en raison de leur prévisibilité et de leur sécurité. Les délégués et protocoles (UIApplicationDelegate, UITableViewDelegate) fournissent des points d'extension explicites sans modifier le runtime. Le sous-classement — créer une sous-classe d'UIViewController en redéfinissant viewDidAppear — fonctionne de manière prévisible et n'a pas de conflits.

SwiftUI et Combine éliminent le besoin de swizzling : les modificateurs (onAppear, onChange) ajoutent du comportement de manière déclarative, sans redéfinir les méthodes. Dans Android Jetpack Compose, le même résultat est obtenu via des effets (LaunchedEffect, SideEffect) et des modificateurs. Les frameworks AOP (AspectJ pour Android, InterposeKit pour iOS) offrent une alternative sûre avec du tissage à la compilation.

Selon les données de l'Apple WWDC 2024, le runtime Swift ne supporte pas le method swizzling au niveau du langage — les méthodes @objc dynamic ne peuvent être swizzlées que via l'Objective-C Runtime. Les applications Swift qui n'utilisent pas @objc sont complètement protégées contre le swizzling accidentel par des bibliothèques tierces. Cela rend Swift plus sûr mais limite les capacités d'instrumentation à l'exécution.

Alternatives déclaratives dans SwiftUI et Compose

Les modificateurs SwiftUI (onAppear, onChange, onReceive) et les effets Jetpack Compose (LaunchedEffect, SideEffect, DisposableEffect) remplacent complètement le swizzling pour les tâches d'interface utilisateur. Ils fournissent un moyen déclaratif, prévisible et testable d'ajouter un comportement transversal sans modifier la table de répartition. Dans les nouveaux projets, Apple et Google recommandent cette approche plutôt que l'interception à l'exécution.

Questions fréquentes

Le Method Swizzling est-il sûr pour la production ?

Le Method Swizzling est acceptable pour la production si les règles sont respectées : dispatch_once pour une exécution unique, appel de l'implémentation originale, tests sur toutes les versions iOS et documentation. Pour les tâches simples, il est préférable d'utiliser des délégués ou le sous-classement. Le swizzling en production est justifié pour les bibliothèques de surveillance et d'analyse.

Quelle est la différence entre Swizzling et AOP ?

Method Swizzling est une technique spécifique pour remplacer les IMPs dans la table de répartition. L'AOP (Programmation Orientée Aspects) est un paradigme dans lequel le swizzling peut être utilisé comme l'un des mécanismes. L'AOP inclut également le tissage à la compilation (AspectJ), l'interception basée sur des proxies (Spring AOP) et la génération de code.

Comment déboguer les problèmes causés par le Swizzling ?

Utiliser un point d'arrêt dans objc_msgSend pour suivre tous les messages. Ajouter un point d'arrêt symbolique sur method_exchangeImplementations avec une condition sur le nom de la classe. L'outil FLEX montre quelles méthodes de la classe sont swizzlées. Pour une vérification systématique, utiliser un script lldb qui affiche la table de répartition de la classe.

Le Swizzling fonctionne-t-il en Swift ?

Swift ne supporte pas le swizzling au niveau du langage. Le Method Swizzling fonctionne uniquement pour les méthodes marquées @objc dynamic, qui sont compilées via l'Objective-C Runtime. Les méthodes Swift pures (sans @objc) utilisent une répartition statique et ne peuvent pas être swizzlées — leur table de répartition n'est pas accessible pour modification.

Quelles bibliothèques iOS utilisent le Swizzling ?

Firebase Analytics (swizzling de viewDidAppear pour le suivi automatique d'écran), Amplitude, Mixpanel, FLEX (inspection UI), OHHTTPStubs (simulation de requêtes réseau), Aspects (framework AOP). Toutes effectuent le swizzling dans +load via dispatch_once avec appel de l'implémentation originale.

Résumé

  • Method Swizzling — échange des IMPs de deux méthodes dans la table de répartition de l'Objective-C Runtime via method_exchangeImplementations.
  • dispatch_once est obligatoire pour prévenir un nouveau swizzling et la récursion.
  • Appeler l'implémentation originale à l'intérieur de la méthode swizzlée est une règle de sécurité obligatoire.
  • Sur Android, le swizzling est remplacé par la réflexion ou la manipulation de bytecode via Gradle Transform / ASM.
  • Risques — conflits de bibliothèques, incompatibilité avec les versions iOS, invisibilité dans le débogueur et interdiction de l'App Review pour les hotfixes.
  • Alternatives — délégués, sous-classement, modificateurs SwiftUI, effets Jetpack Compose.
  • Les méthodes Swift sans @objc dynamic sont protégées du swizzling, ce qui améliore la stabilité mais limite l'instrumentation à l'exécution.

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi