Découvrez pourquoi Apple a créé Swift, comment il a progressivement remplacé Objective‑C dans les apps iOS, et ce que ce changement implique pour les outils, le recrutement et les bases de code aujourd'hui.

Swift n'est pas apparu simplement parce qu'Apple voulait un nouveau langage « pour le plaisir ». Il a été conçu en réponse à des points de douleur réels dans le développement iOS : itérations lentes, patterns dangereux faciles à écrire par erreur, et un décalage croissant entre la complexité des apps modernes et la conception plus ancienne d'Objective‑C.
Cet article répond à une question pratique : pourquoi Swift existe, comment il est devenu le langage par défaut, et pourquoi cette histoire influence encore aujourd'hui vos décisions de codebase et d'équipe.
Vous aurez une chronologie claire et légère — des premières versions de Swift à une chaîne d'outils stable et largement adoptée — sans vous perdre dans des détails triviaux. En chemin, nous relierons l'histoire aux conséquences quotidiennes : comment les développeurs écrivent du code plus sûr, comment les API ont évolué, ce qui a changé dans les workflows Xcode, et ce que signifie le « Swift moderne » avec des fonctionnalités comme la concurrence et SwiftUI.
Objective‑C est encore présent dans de nombreuses apps réussies, surtout dans les bases de code plus anciennes et certaines bibliothèques. L'objectif n'est pas d'alarmer mais d'éclairer : Swift n'a pas effacé Objective‑C du jour au lendemain ; il l'a supplanté progressivement via l'interopérabilité et des changements d'écosystème.
Objective‑C a été la fondation du développement Apple pendant des décennies. Quand le premier SDK iPhone est arrivé en 2008, Objective‑C (et les frameworks Cocoa Touch) était le moyen principal de construire des apps, tout comme il l'avait été pour Mac OS X avec Cocoa. Si vous développiez des apps iOS à l'époque, vous appreniez les conventions de la plateforme Apple via Objective‑C.
Objective‑C avait beaucoup d'atouts — surtout si l'on adhérait à la « façon Cocoa » de construire le logiciel.
Il reposait sur un runtime dynamique puissant : messaging, introspection, catégories et method swizzling permettaient des patterns flexibles et « plug‑in ». Les conventions Cocoa comme delegation, target–action, notifications et KVC/KVO (key‑value coding/observing) étaient profondément intégrées et bien documentées.
Autre point important : un écosystème mature. Les frameworks Apple, les bibliothèques tierces et des années de réponses sur Stack Overflow supposaient Objective‑C. Les outils et API étaient conçus autour de ce langage, et les équipes pouvaient recruter des développeurs avec des compétences prévisibles.
Les problèmes n'étaient pas philosophiques — ils étaient pratiques et quotidiens.
Objective‑C pouvait être verbeux, surtout pour des tâches « simples ». Les signatures de méthodes, les crochets et le boilerplate rendaient le code plus long et plus difficile à parcourir. Beaucoup d'API exposaient des concepts lourds en pointeurs, augmentant le risque d'erreurs, en particulier avant la généralisation de l'ARC (Automatic Reference Counting).
La mémoire et la sécurité restaient des sujets : même avec ARC, il fallait comprendre la propriété, les cycles de références et comment la nullabilité pouvait vous surprendre à l'exécution.
L'interfaçage avec les APIs C était courant — et pas toujours agréable. Faire le bridge des types C, gérer Core Foundation et le « toll‑free bridging » ajoutait une charge mentale qui ne ressemblait pas à l'écriture de code applicatif moderne.
Les bases de code iOS héritées s'appuient souvent sur Objective‑C parce qu'elles sont stables, éprouvées et coûteuses à réécrire. Beaucoup d'apps de longue durée incluent des couches Objective‑C (ou des dépendances anciennes) qui font encore un vrai travail — et le font de manière fiable.
Apple n'a pas créé Swift parce qu'Objective‑C était « cassé ». Objective‑C avait permis des années d'apps iPhone et Mac réussies. Mais à mesure que les apps grandissaient, les équipes s'élargissaient et les API se multipliaient, le coût de certains défauts par défaut d'Objective‑C est devenu plus visible — surtout quand on multiplie de petits risques sur des millions de lignes de code.
Un objectif majeur était de rendre les erreurs courantes plus difficiles à écrire. La flexibilité d'Objective‑C est puissante, mais elle peut masquer des problèmes jusqu'à l'exécution : envoyer des messages à nil, confondre des types id, ou mal gérer la nullabilité des API. Beaucoup de ces problèmes étaient gérables avec de la discipline, des conventions et de bonnes revues, mais restaient coûteux à grande échelle.
Swift intègre des garde‑fous : les optionnels vous obligent à penser « est‑ce que ça peut manquer ? », le typage fort réduit les usages accidentels, et des fonctionnalités comme guard, l'exhaustivité des switch et une manipulation plus sûre des collections déplacent davantage de bugs vers le temps de compilation plutôt que la production.
Swift a aussi modernisé l'expérience quotidienne d'écriture de code. Une syntaxe concise, l'inférence de type et une bibliothèque standard plus riche rendent beaucoup de tâches plus claires avec moins de boilerplate que les patterns header/implementation, les bricolages de generics ou l'utilisation intensive de macros.
Sur les performances, Swift a été conçu pour permettre des optimisations agressives du compilateur (notamment avec les types valeur et les generics). Cela ne garantit pas qu'une app Swift soit automatiquement plus rapide qu'une app Objective‑C, mais cela fournit à Apple un modèle de langage qui peut évoluer vers la vitesse sans dépendre autant du runtime dynamique.
Apple avait besoin que le développement iOS soit abordable pour les nouveaux développeurs et durable pour les produits de longue durée. Les conventions de nommage des API Swift, l'intention plus claire sur les sites d'appel et l'accent sur des types expressifs visent à réduire le « savoir tribal » et à rendre les bases de code plus faciles à relire plusieurs mois plus tard.
Le résultat : moins de pièges, des API plus propres, et un langage qui aide mieux les grandes équipes à maintenir des apps pendant des années — sans prétendre qu'Objective‑C ne pouvait pas faire le travail.
Swift n'a pas « gagné » du jour au lendemain. Apple l'a présenté comme une meilleure option pour le code neuf, puis a passé des années à le rendre stable, plus rapide et plus simple à adopter aux côtés des apps Objective‑C existantes.
La stabilité ABI signifie que le runtime Swift et les bibliothèques standard sont compatibles au niveau binaire entre les versions Swift 5 sur les plateformes Apple. Avant Swift 5, beaucoup d'apps devaient embarquer les bibliothèques Swift dans l'app, augmentant la taille et compliquant la distribution. Avec la stabilité ABI, Swift est devenu plus similaire à Objective‑C en fiabilité d'exécution entre mises à jour d'OS, aidant Swift à paraître « sûr » pour les bases de code de production de longue durée.
Pendant des années, beaucoup d'équipes ont utilisé Swift pour les nouvelles fonctionnalités tout en laissant des modules cœur en Objective‑C. Ce chemin par étapes — plutôt que la réécriture totale — a rendu l'ascension de Swift pratique pour des apps réelles et des deadlines réelles.
Swift n'a pas gagné en forçant chaque équipe à jeter du code Objective‑C fonctionnel. Apple a garanti que les deux langages puissent coexister dans la même cible d'app. Cette compatibilité est une grosse raison pour laquelle l'adoption de Swift n'a pas buté dès le premier jour.
Une base de code mixte est normale sur iOS : vous pouvez garder des composants réseau, analytics ou UI en Objective‑C tout en écrivant de nouvelles fonctionnalités en Swift. Xcode supporte cela directement, donc « Swift a remplacé Objective‑C » signifie généralement un changement incrémental, pas une réécriture massive.
L'interopérabilité fonctionne via deux mécanismes complémentaires :
YourModuleName-Swift.h) qui expose les classes et méthodes Swift compatibles Objective‑C. On opte en général pour cela avec des attributs comme @objc (ou en héritant de NSObject).Vous n'avez pas besoin de mémoriser toute la plomberie pour en tirer parti — mais comprendre qu'il y a une étape explicite « exposer ceci à l'autre langage » aide à expliquer pourquoi certains types apparaissent automatiquement et d'autres non.
La plupart des équipes rencontrent quelques points d'intégration récurrents :
Les vraies apps vivent longtemps. L'interopérabilité vous permet de migrer fonctionnalité par fonctionnalité, continuer à livrer et réduire le risque — surtout quand des SDKs tiers, des composants anciens ou des contraintes de temps rendent irréaliste une conversion totale.
Swift n'a pas seulement modernisé la syntaxe — il a changé l'apparence du code iOS « normal » au quotidien. Beaucoup de patterns qui reposaient auparavant sur des conventions (et des revues attentives) sont devenus des choses que le compilateur peut aider à faire respecter.
Les développeurs Objective‑C avaient l'habitude que l'envoi de messages à nil ne fasse rien silencieusement. Swift rend l'absence explicite avec les optionnels (String?), vous poussant à gérer les valeurs manquantes en amont avec if let, guard ou ??. Cela prévient toute une catégorie de crashs et de bugs liés à « pourquoi ceci est vide ? » — sans prétendre que les erreurs ne peuvent plus arriver.
Swift peut inférer les types à de nombreux endroits, ce qui coupe le boilerplate tout en gardant le code lisible :
let title = "Settings" // inferred as String
Plus important, les generics permettent d'écrire du code réutilisable et typé sans s'appuyer sur id et des vérifications runtime. Comparer « tableau de n'importe quoi » versus « tableau de ce que j'attends exactement » réduit les objets inattendus qui se glissent et les casts forcés.
Le throw/try/catch de Swift encourage des chemins d'erreur explicites au lieu d'ignorer les échecs ou de propager des NSError **. Les collections sont fortement typées ([User], [String: Int]), et les chaînes sont des String Unicode correctes plutôt qu'un mélange de C strings, NSString et décisions d'encodage manuelles. L'effet net est moins d'erreurs off‑by‑one, moins d'hypothèses invalides et moins de « ça compile mais casse à l'exécution ».
Le runtime d'Objective‑C reste précieux pour des patterns fortement orientés runtime : method swizzling, forward de messages dynamiques, certaines approches d'injection de dépendances, et du code piloté par KVC/KVO. Swift peut interopérer avec ces mécanismes, mais quand vous avez vraiment besoin de dynamisme à l'exécution, Objective‑C reste un outil pratique.
Swift n'a pas seulement changé la syntaxe — il a poussé l'écosystème iOS à moderniser ses outils et conventions. Cette transition n'a pas toujours été fluide : les premières versions de Swift pouvaient signifier des builds plus lents, une autocomplétion moins fiable et des refactors plus risqués qu'ils ne devraient l'être. Avec le temps, l'expérience développeur est devenue un des plus grands avantages de Swift.
Le support Swift dans Xcode s'est amélioré de façon concrète :
Si vous avez utilisé Swift aux versions 1.x/2.x, vous vous souvenez peut‑être des aspérités. Depuis, la tendance est constante : meilleur indexage, meilleure stabilité des sources et bien moins de moments « Xcode est perdu ».
Swift Package Manager (SPM) a réduit le besoin de systèmes de dépendances externes pour beaucoup d'équipes. Au niveau basique, vous déclarez des packages et des versions, Xcode les résout, et la construction s'intègre sans gymnastique de fichiers de projet. Ce n'est pas parfait pour tous les setups, mais pour de nombreuses apps cela a simplifié l'onboarding et rendu les mises à jour de dépendances plus prévisibles.
Les Apple API Design Guidelines ont poussé les frameworks vers un nommage plus clair, de meilleurs comportements par défaut et des types qui communiquent l'intention. Cette influence s'est diffusée : les bibliothèques tierces ont de plus en plus adopté des API Swift‑first, rendant les bases de code iOS modernes plus cohérentes — même quand il y a un bridge Objective‑C en-dessous.
UIKit n'a pas disparu. La majorité des apps iOS en production s'en appuient encore fortement, surtout pour la navigation complexe, les gestes fins, le traitement avancé du texte et la longue traîne de composants UI éprouvés. Ce qui a changé, c'est que Swift est désormais le moyen par défaut d'écrire du code UIKit — même si le framework sous‑jacent est le même.
Pour beaucoup d'équipes, « app UIKit » n'implique plus Objective‑C. Storyboards, nibs et vues programmatiques sont couramment pilotés par des view controllers et des modèles Swift.
Ce changement compte parce qu'Apple conçoit de plus en plus de nouvelles API en pensant l'ergonomie Swift (nommage plus clair, optionnels, generics, types résultat). Même quand une API existe pour Objective‑C, la surcouche Swift donne souvent l'impression d'être la surface « prévue », ce qui accélère la montée en compétence des nouveaux développeurs dans une base UIKit.
SwiftUI n'a pas été qu'une nouvelle façon d'afficher des boutons. Il a poussé un modèle mental différent :
Concrètement, cela a changé les discussions d'architecture. Les équipes qui adoptent SwiftUI mettent souvent l'accent sur le flux de données unidirectionnel, des composants de vue plus petits et l'isolation des effets de bord (réseau, persistance) hors du code de vue. Même si vous n'allez pas « tout faire » en SwiftUI, il simplifie les écrans principalement composés de formulaires, listes et mises en page pilotées par l'état.
Les apps en production combinent fréquemment les deux frameworks :
UIHostingController pour de nouveaux écrans.Cette approche hybride permet de garder l'infrastructure UIKit mature — piles de navigation, coordinators, design systems existants — tout en adoptant SwiftUI de façon incrémentale là où il apporte un bénéfice clair. Elle maintient aussi le risque à un niveau gérable : vous pouvez piloter SwiftUI sur des zones limitées sans réécrire toute la couche UI.
Si vous démarrez aujourd'hui, la nouvelle histoire UI d'Apple est SwiftUI, et beaucoup de technologies adjacentes (widgets, Live Activities, certaines extensions) sont fortement orientées Swift. Même hors UI, les API favorables à Swift sur les plateformes Apple tendent à orienter les choix par défaut : les nouveaux projets sont généralement prévus avec Swift, et la question devient « combien de UIKit avons‑nous besoin ? » plutôt que « devons‑nous utiliser Objective‑C ? »
Le résultat n'est pas tant la disparition d'un framework au profit d'un autre que le fait que Swift devient la langue commune, à la fois pour la voie legacy‑friendly (UIKit) et la voie plus récente, native Swift (SwiftUI).
La concurrence, c'est la façon dont une app fait plusieurs choses « en même temps » — charger des données, décoder du JSON et mettre à jour l'écran — sans figer l'interface. L'approche moderne de Swift vise à rendre ce travail plus lisible, comme du code normal, et moins comme de la jonglerie de threads.
Avec async/await, vous pouvez écrire du travail asynchrone (comme une requête réseau) dans un style linéaire :
async marque une fonction qui peut se mettre en pause en attendant quelque chose.await est le point « pause ici jusqu'à ce que le résultat soit prêt ».Au lieu d'imbriquer des handlers de completion, vous le lisez comme une recette : fetch, parse, update.
Swift associe async/await à la concurrence structurée, ce qui signifie essentiellement : « le travail en arrière‑plan doit avoir un propriétaire et une durée de vie clairs. » Les tâches sont créées dans un scope et les tâches enfants sont liées à leur parent.
Cela améliore :
Deux concepts aident à réduire les crashs liés aux accès simultanés :
La plupart des équipes n'activent pas tout d'un coup. Il est courant de mélanger la concurrence moderne Swift avec d'anciens patterns — OperationQueue, GCD, callbacks et completion handlers — surtout quand on intègre des bibliothèques legacy ou des flows UIKit plus anciens.
Migrer une vraie app iOS n'est pas un projet « tout convertir » — c'est un projet de gestion des risques. L'objectif est de continuer à livrer tout en réduisant progressivement la part d'Objective‑C à maintenir.
Une approche courante est la migration incrémentale :
Cela vous permet de construire de la confiance tout en contenant le rayon d'impact — particulièrement utile quand les deadlines ne permettent pas de bloquer pour une transition linguistique.
Plusieurs patterns Objective‑C ne se traduisent pas proprement :
objc_runtime intensif peut nécessiter une refonte plutôt qu'une traduction.Considérez la migration comme un échange d'implémentation, pas un changement de fonctionnalité. Ajoutez d'abord des tests de caractérisation autour des flux critiques (réseau, cache, paiements, auth), puis portez. Les tests de snapshot aident à détecter les régressions UI quand du code UIKit bouge vers Swift.
Créez une norme légère pour les équipes : conventions de code, linting (SwiftLint ou équivalent), frontières de module, règles de bridging header et « pas de nouvel Objective‑C sauf justification ». L'écrire empêche la base de code de devenir bilingue de manière incohérente.
Swift n'a pas seulement changé la syntaxe — il a changé ce qui est « normal » dans une équipe iOS. Même si votre produit contient encore de l'Objective‑C, les décisions quotidiennes sur les personnes, les processus et la maintenance long terme sont maintenant influencées par des attentes orientées Swift.
La plupart des offres iOS supposent Swift par défaut. Les candidats peuvent n'avoir jamais livré en Objective‑C professionnellement, ce qui rallonge le temps d'adaptation si la base est mixte.
Pratique à retenir : considérez la connaissance d'Objective‑C comme un « plus », pas comme un prérequis, et fournissez des docs d'onboarding claires indiquant où l'Objective‑C existe et pourquoi. Un guide interne court sur les bridging headers, la propriété des fichiers et les zones « ne pas toucher sans contexte » évite des erreurs précoces.
Le typage fort de Swift et les optionnels clairs peuvent rendre les revues plus rapides : les relecteurs passent moins de temps à deviner ce qu'une valeur peut être et plus de temps à valider l'intention. Des patterns comme les protocols, les generics et les types valeur encouragent aussi une architecture plus consistante — lorsqu'ils sont utilisés avec retenue.
Le revers de la médaille est la dérive de style. Les équipes gagnent à avoir un guide de style Swift partagé et du formatage/linting automatisé pour que les revues portent sur le comportement, pas sur l'indentation. (Si vous avez déjà des règles, liez‑les depuis votre hub de docs interne.)
La maintenance devient plus simple quand vous pouvez utiliser directement des API modernes au lieu de porter des wrappers personnalisés construits autour d'anciens patterns. Mais Objective‑C ne disparaîtra pas du jour au lendemain — surtout dans les apps matures avec des modules éprouvés.
Budgetez de façon réaliste pour des bases mixtes : planifiez la migration autour de jalons métier, pas comme un nettoyage sans fin. Définissez ce que signifie « fini » (par ex. tout nouveau code en Swift, modules legacy touchés seulement de façon opportuniste) et revisitez cette règle lors de refactors majeurs.
Pour un cadre de décision, voyez /blog/migrating-objective-c-to-swift.
Choisir entre Swift et Objective‑C n'est généralement pas un débat philosophique — c'est une décision de coût, de risque et de planning. La bonne nouvelle : vous avez rarement à choisir « tout ou rien ». La plupart des équipes obtiennent le meilleur résultat en faisant évoluer la base de code sur place.
Si vous démarrez un projet, Swift devrait être la valeur par défaut. Il s'aligne sur les API les plus récentes d'Apple, offre de meilleures garanties de sécurité et donne un accès direct aux patterns modernes comme async/await.
Votre première décision porte sur la stratégie UI : UIKit en Swift, SwiftUI ou un mix. Si vous hésitez, comparez les compromis dans /blog/swiftui-vs-uikit.
Pour une app Objective‑C existante, conservez les modules stables et testés en Objective‑C et introduisez Swift là où vous en tirerez un bénéfice rapide :
Règle pratique : créez un nouveau module Swift quand vous pouvez définir des frontières claires (surface API, propriété, tests). Gardez Objective‑C stable quand le code est mature, fortement imbriqué ou risqué à toucher sans refactor global.
Pour la planification, consultez /blog/ios-migration-checklist.
Pour les individus et les équipes, cette séquence correspond bien au développement iOS quotidien :
La modernisation iOS met souvent en lumière du travail « adjacent » qui concurrence le même temps ingénierie : dashboards admin, outils internes, services backend et APIs dont l'app dépend. Si vous voulez garder votre équipe iOS concentrée sur la migration vers Swift tout en continuant à livrer le logiciel de support, Koder.ai peut vous aider à lancer des web apps, backends Go (avec PostgreSQL) ou apps compagnon Flutter via un workflow piloté par chat — puis exporter le code source, déployer et gérer les itérations avec snapshots/rollback.
Si vous voulez de l'aide externe pour cadrer la prochaine étape la plus sûre — nouveau module, migration partielle ou « ne rien toucher » — voyez /pricing.
Swift a été créé pour réduire les risques courants du développement iOS (comme le comportement inattendu de nil et le typage lâche), améliorer la lisibilité et la maintenabilité des grandes bases de code, et permettre des optimisations plus fortes du compilateur sur le long terme. Il ne s'agit pas de dire qu'Objective‑C était « mauvais » : c'était plutôt rendre les choix sûrs et modernes plus faciles à utiliser à grande échelle.
Swift est devenu la langue par défaut grâce à une progression graduelle combinant plusieurs facteurs :
Tout cela a rendu « écrire du nouveau code en Swift » le chemin de moindre résistance pour la plupart des équipes.
Swift 5 a introduit la stabilité ABI sur les plateformes Apple, ce qui signifie que le code Swift compilé peut rester binaire‑compatible entre les versions Swift 5.x fournies par le système d'exploitation. Concrètement, cela a réduit la nécessité d'inclure les bibliothèques Swift dans l'app, amélioré la taille des apps et la fiabilité du déploiement, et renforcé la confiance à long terme pour du code de production.
On peut mélanger les deux dans une même cible d'app :
YourModuleName-Swift.h, en utilisant typiquement @objc et/ou en héritant de NSObject.Toutes les fonctionnalités Swift ne sont pas visibles depuis Objective‑C, donc il faut définir des frontières intentionnelles.
Les optionnels (T?) rendent l'« absence de valeur » explicite et forcent un traitement à la compilation (par exemple if let, guard, ??). En Objective‑C, l'envoi de messages à nil et la nullabilité ambiguë peuvent cacher des bugs jusqu'à l'exécution. Le gain pratique est moins de plantages et moins d'erreurs du type « cette valeur était vide de façon inattendue ».
Les génériques et le typage fort de Swift réduisent les casts et les vérifications de type à l'exécution (fréquents avec id et les collections non typées en Objective‑C). Concrètement, vous obtenez :
[User] au lieu d'« un tableau de n'importe quoi » ;Oui — Objective‑C reste pertinent lorsqu'on a vraiment besoin de dynamisme à l'exécution (par exemple usage intensif de KVC/KVO, method swizzling, API basées sur des selectors ou certaines architectures plugin). Swift peut interagir avec ces patterns, mais des équivalents purement Swift demandent souvent une refonte plutôt qu'une traduction directe.
Approche pratique et incrémentale :
Considérez la migration comme de la gestion de risque : continuez à livrer tout en réduisant progressivement le coût de maintenance à long terme.
Les pièges courants comprennent :
@objc, NSObject et des fonctionnalités limitées).Planifiez des frontières claires et ajoutez des tests avant d'échanger des implémentations.
Pas du tout. De nombreuses apps en production sont hybrides :
UIHostingController pour intégrer des écrans SwiftUI dans UIKit.Cela permet d'adopter SwiftUI là où il réduit la verbosité tout en conservant la navigation, l'infrastructure et les composants complexes déjà éprouvés en UIKit.