
-
Nouveautés dans Swift
Rejoignez-nous pour une mise à jour sur Swift. Nous parlerons des améliorations apportées au workflow qui vous rendront plus productif, ainsi que des nouvelles API de bibliothèque modernisées pour les tâches de programmation fondamentales. Nous montrerons des exemples d'adoption de Swift à travers d'autres couches de la pile logicielle. Enfin, nous explorerons de nouvelles fonctionnalités de langage visant à améliorer l'utilisation de la concurrence et à atteindre des performances optimales lorsque vous en avez besoin.
Chapitres
- 0:00 - Introduction et ordre du jour
- 0:48 - Mises à jour de swiftlang
- 3:06 - Workflow de développement : Écriture de code
- 4:40 - Workflow de développement : Création
- 7:36 - Workflow de développement : Débogage
- 9:14 - Bibliothèques : Sous-processus
- 10:45 - Bibliothèques : Foundation
- 12:31 - Bibliothèques : Observation
- 14:13 - Bibliothèques : Test
- 16:08 - Swift à tous les niveaux : Swift embarqué
- 18:00 - Swift à tous les niveaux : Sécurité
- 19:37 - Swift à tous les niveaux : Serveur
- 23:23 - Swift à tous les niveaux : Plates-formes
- 26:11 - Évolution du langage : Performances
- 30:28 - Évolution du langage : Concurrence
- 37:15 - Conclusion
Ressources
Vidéos connexes
WWDC25
- Adoptez la concurrence avec Swift
- Améliorer l’utilisation de la mémoire et les performances avec Swift
- Code-along : Améliorez une app avec la concurrence Swift
- Découvrez Containerization
- Découvrir l’interopérabilité entre Swift et Java
- Mixez en toute sécurité C, C++ et Swift
WWDC24
-
Rechercher dans cette vidéo…
Bonjour et bienvenue dans la section Nouveautés de Swift. Je m’appelle Holly. Et moi Allan. Nous vous présentons les nouvelles fonctionnalités et améliorations de Swift 6.2. Ces améliorations vous permettent d’être plus productif avec Swift, quel que soit le code que vous utilisez ou l’endroit où vous l’insérez. Voyons d’abord les améliorations du flux de travail pour l’écriture, la création et le débogage de code. Ensuite, nous abordons les nouvelles API de bibliothèque pour les tâches de programmation fondamentales. Nous vous montrons aussi comment Swift peut être adopté à chaque couche de la pile logicielle. Enfin, nous explorons de nouvelles fonctionnalités de langage qui boostent vos performances quand vous en avez besoin. Tous ces changements ont été développés ensemble en open source. swiftlang sur GitHub a développé plus de 50 projets, dont le compilateur, le site web swift.org, les bibliothèques de base et de test, et d’autres composants clés. Nous avons migré des projets vers swiftlang et mis Swift Build, le système de compilation de Xcode, en open source. Swift Build prend en charge le processus de compilation pour les systèmes d’exploitation d’Apple. Swift Build devrait être adopté comme système de compilation Open source de bas niveau du Swift Package Manager. Cela unifiera le moteur de compilation entre Xcode et les chaînes d’outils Swift.org. Pour en savoir plus sur Swift Build, lisez « The Next Chapter in Swift Build Technologie » sur le blog. Dernier-né du projet swiftlang : Swiftly, un gestionnaire de versions. Swiftly a d’abord été développé en open source pour rationaliser la gestion de la chaîne d’outils Swift sous Linux. Swiftly prend désormais en charge macOS, et la version 1.0 est disponible sur swift.org. La dernière chaîne d’outils Swift s’installe en une seule commande. Vous pouvez également installer une version nocturne à partir d’une branche GitHub pour essayer les fonctionnalités de langage en cours de développement. Dans Xcode, les chaînes d’outils installées par Swiftly sont disponibles dans le menu de la chaîne d’outils. N’oubliez pas que si vous compilez une app, vous devez utiliser la chaîne d’outils Xcode pour soumettre votre app sur l’App Store. Dans VS Code, vous pouvez sélectionner des chaînes d’outils installées par Swiftly à partir de la commande Chaîne d’outils. Vous pouvez en savoir plus sur Swiftly 1.0 sur le blog Swift. Les améliorations de Swift ne se limitent pas à l’installation des outils. La page d’accueil swift.org a un nouveau look pour vous aider dans différents domaines : apps, services cloud, systèmes embarqués, etc. C’est une collaboration avec le groupe de travail du site web Swift. Se lancer avec Swift n’a jamais été aussi simple. Allan vous montre comment Swift 6.2 offre plus de flexibilité pour créer un environnement de développement qui répond à vos besoins. Merci, Holly. La nouvelle version de Swift vous permet d’améliorer les flux de développement, quelle que soit votre méthode d’écriture du code Swift. Ces améliorations couvrent un large éventail de processus : écriture de code, compilation, débogage. Commençons par voir ce qui vous attend si vous développez dans VS Code.
L’extension Swift sur le marketplace VS Code est maintenant officiellement distribuée par swift.org. Elle s’est étoffée de nouvelles fonctions en cours d’année. La première est l’indexation en arrière-plan. Dans Swift 6.1, l’indexation en arrière-plan est activée par défaut pour les projets Swift PM dans VS Code et d’autres IDE. Cela permet aux fonctions telles que Aller à la définition de rester à jour quand vous modifiez votre projet. Les résultats de saisie semi-automatique du code dans VS Code sont plus pertinents, grâce aux améliorations apportées à SourceKit-LSP. Le débogage a également été simplifié. La prise en charge de LLDB est incluse automatiquement lorsque vous installez l’extension Swift. La dernière version de l’extension comprend un nouveau panneau de projet, qui facilite la recherche des dépendances, des cibles et des tâches de votre package. L’extension Swift pour VS Code propose une nouvelle façon de consulter la documentation de votre projet. Vous pouvez afficher un aperçu DocC côte à côte avec votre code, et il se mettra à jour à mesure que vous tapez. L’extension Swift pour VS Code est développée en open source, et vous pouvez la trouver sur GitHub dans l’organisation swiftlang. Parlons des améliorations apportées à la création de code Swift qui sont disponibles partout. La performance de vos outils est essentielle pour votre productivité.
Swift 6.2 améliore les temps de compilation à neuf pour les projets qui utilisent des API basées sur des macros. Par exemple, vous avez un projet qui utilise une macro d’un package imaginaire appelé Stringify. Pour compiler vos projets, Swift PM devait d’abord récupérer les sources de swift-syntax, une bibliothèque qui alimente les macros. Ensuite, il compilait swift-syntax, le plugin macro Stringify et enfin, votre code. Swift-syntax pouvait être mis en cache, mais cela ralentissait quand même le temps de compilation. Cela est particulièrement perceptible dans un environnement d’intégration continue. Pour accélérer votre compilation, les dernières versions de Swift PM et de Xcode prennent en charge les dépendances swift-syntax précompilées. Cela élimine complètement une étape coûteuse et peut faire gagner plusieurs minutes.
Si votre paquet fournit des macros, vos clients pourront profiter de cette optimisation tant que le paquet dépend d’une version taguée de swift-syntax. Mais, votre productivité ne dépend pas seulement de la compilation. Essayer de résoudre les problèmes trouvés par le compilateur est ce qui vous ralentit. Par exemple, lorsque vous écrivez du code concurrent en Swift 6, le compilateur peut détecter des accès concurrents aux données que vous devez empêcher. C’est important, mais cela ne signifie pas que c’est facile à résoudre. Dans Swift 6.2, nous avons étendu la documentation disponible pour de nombreuses catégories de diagnostics. Ces explications des avertissements et erreurs courants vous aident à comprendre le problème et vous donnent des solutions concrètes. Vous pouvez accéder à la documentation depuis votre IDE et en ligne sur swift.org. Contrôler le comportement des diagnostics est également important. Par exemple, pour garder le code exempt d’avertissements, vous pouvez utiliser le paramètre « warnings as errors ». C’est pratique pour les avertissements simples à traiter, mais vous ne voulez pas toujours devoir les résoudre tous immédiatement. SWIFT 6.2 vous permet de décider quels avertissements traiter comme des erreurs. Vous pouvez décider de traiter tous les avertissements comme des erreurs par défaut, ou faire une exception pour les déclarations obsolètes. Mais si vous ne voulez empêcher que certaines catégories d’avertissements, vous pouvez simplement les transformer en erreurs. L’ajout de contrôles pour les avertissements du compilateur est un exemple d’effort visant à améliorer Swift pour toute la communauté. Merci aux auteurs des propositions et à tous ceux qui ont participé aux discussions sur les forums. Enfin, examinons certaines améliorations importantes du débogage dans Swift 6.2.
Dans cette version, nous avons amélioré l’expérience de débogage du code asynchrone. Lorsque vous parcourez le code exécuté dans une tâche Swift, LLDB suit l’exécution dans des fonctions asynchrones, même si cela nécessite de basculer entre les threads. La compréhension par les débogueurs du modèle centré sur les tâches de Swift leur permet d’indiquer quelle tâche s’exécute. Vous pouvez même nommer une tâche pour l’identifier plus facilement. Les noms de tâches apparaissent aussi dans les profils Instruments enregistrés dans le modèle de concurrence d’Instruments. Vous pouvez utiliser de nouvelles commandes telles que swift task info pour obtenir plus d’infos sur la tâche en cours d’exécution, telles que sa priorité et les tâches enfants. Le débogage devient plus réactif, grâce aux modules construits explicitement qui permettent le parallélisme et la réutilisation lors de la création de dépendances de modules. Avant les modules construits explicitement, le compilateur de Xcode et le débogueur utilisaient chacun leur propre graphe de module. Le débogueur peut maintenant réutiliser les modules de la compilation. La première fois que vous exécutez p ou po dans le débogueur, la commande évalue plus rapidement, car les infos de type sont immédiatement disponibles. Les modules construits explicitement sont activés par défaut dans Xcode 26. Ce ne sont là que quelques-unes des améliorations apportées à Swift cette année. Voici quelques mises à jour importantes apportées aux principales bibliothèques Swift les plus utilisées. Les bibliothèques sont très utiles, et celles de Swift sont essentielles pour le codage. Swift 6.2 modernise une grande partie des APIs de Foundation et en fournit de nouvelles pour faciliter la programmation. Pour faciliter l’utilisation de Swift, le groupe de travail Foundation a introduit un nouveau package avec des API permettant de lancer un sous-processus. Vous commencez par ajouter et importer le nouveau package de sous-processus. Ensuite, vous lancez un sous-processus en appelant la fonction exécutable et en attendant le résultat. Si vous fournissez une chaîne avec le nom du processus, la méthode run recherche l’exécutable en fonction de la variable d’environnement $PATH.
Généralement, vous lancez un sous-processus avec un FilePath pour spécifier le chemin d’accès complet à un exécutable. Lorsque le sous-processus se termine, vous pouvez inspecter l’état de sortie, la sortie standard et d’autres informations sur l’exécution du processus. La bibliothèque de sous-processus possède d’autres fonctionnalités qui vous donnent un contrôle sur l’exécution des processus, les options de configuration spécifiques à la plate-forme, etc. Vous pouvez explorer toute la surface de l’API dans le dépôt swift-subprocess. Le paquet en est à la version 0.1 et votre feedback contribuera à définir l’API qui sera publiée en version 1.0. Le groupe de travail Foundation a également amélioré les API courantes utilisées dans les projets d’app. Répondre aux notifications d’UIKit est très courant dans les apps iOS, mais le code permettant d’observer une notification est sujet à des erreurs. Tout d’abord, vous devez veiller à vous enregistrer pour un nom de notification que l’objet peut publier. Si vous faites une erreur, votre callback de notification ne s’exécutera jamais. Les infos de la notification sont stockées dans un dictionnaire non typé, ce qui oblige à accéder manuellement aux valeurs via la clé appropriée et à effectuer une conversion dynamique vers le type correct. Même lorsque la notification est garantie d’être publiée sur le thread principal, vous obtenez toujours des erreurs de concurrence lors de l’accès aux API de main actor. Les noms et les charges utiles des notifications prennent désormais en charge les types concrets. Les types concrets permettent au compilateur de vérifier que l’objet prend en charge le type de notification pour lequel vous vous enregistrez. Ils éliminent également le code répétitif lors de l’utilisation de la charge utile d’une notification. Le type de notification spécifie où celle-ci est postée. Si la notification est postée sur le main actor, vous pouvez accéder librement à ses API. Une conformité à MainActorMessage garantit que la notification est toujours postée de manière synchrone sur le thread principal. Une conformité à AsyncMessage signifie que la notification est postée de manière asynchrone sur un thread arbitraire. Des types concrets de notifications sont disponibles dans le SDK pour les notifications émises par des frameworks tels que UIKit et Foundation. Vous pouvez ajouter des types concrets de notifications pour vos propres notifications. La diffusion des notifications du système aux observateurs enregistrés repose sur un modèle d’observateur plus général. La bibliothèque Observation fournit des API à usage général pour suivre automatiquement les changements d’état dans un graphe d’objets.
Vous pouvez activer le suivi des changements d’état pour une classe en utilisant la macro @Observable. Swift 6.2 introduit un moyen de diffuser en continu les changements d’état avec un AsyncSequence à partir d’un type observable. Vous commencez par créer une instance du nouveau type d’observations avec une fermeture. Dans la fermeture, vous calculez la valeur à laquelle vous souhaitez observer les modifications. Ici, je veux observer la chaîne décrivant l’état actuel du joueur, et je veux une nouvelle valeur chaque fois que le score est mis à jour ou que le joueur obtient un nouvel objet. Vous obtenez une valeur mise à jour basée sur les propriétés observables utilisées dans la fermeture. Les mises à jour se font de manière transactionnelle. Le suivi d’une mise à jour commence lorsque l’une des propriétés observables de la fermeture voit son willSet appelé. Il se termine à la prochaine attente où le code se suspend. La valeur mise à jour comprend toutes les modifications synchrones apportées aux autres propriétés entre ces deux points du code. Cela garantit que les mises à jour synchrones de plusieurs propriétés n’entraînent pas de mises à jour d’observation avec l’objet dans un état incohérent.
Si je mets à jour de manière synchrone le score et l’élément, j’obtiens une seule valeur mise à jour contenant les deux modifications. Le type d’observations est conforme à AsyncSequence, ce qui vous permet d’itérer sur des valeurs mises à jour à l’aide d’une boucle for-await. En tant que développeurs, nous écrivons des tests tous les jours. Swift Testing est une bibliothèque multiplateforme qui fournit des macros pour décrire et organiser vos tests, comme l’attribut @Test pour déclarer une fonction de test. Vous utilisez les macros expect et require pour valider vos hypothèses, et Swift Testing vous fournit des infos exploitables lorsqu’une attente ou une exigence échoue. Parfois, les échecs de test sont difficiles à trier, surtout s’ils échouent uniquement dans des environnements distants comme CI. La compréhension d’un échec de test peut nécessiter plus de contexte sur les données utilisées.
Swift 6.2 introduit des pièces jointes personnalisées pour vous aider à diagnostiquer les échecs de test. Vous pouvez ajouter une pièce jointe à un test en appelant la méthode Attachment.record. Vous pouvez attacher des types de bibliothèque tels que Data et String, et vous pouvez implémenter la prise en charge des pièces jointes pour vos propres types en vous conformant au protocole attachable. Swift 6.2 prend également en charge les tests de terminaison, ce qui vous permet de tester le code que vous prévoyez d’arrêter sous certaines conditions. Par exemple, si vous écrivez une fonction qui valide les hypothèses sur les paramètres d’entrée à l’aide de préconditions, vous pouvez écrire un cas de test qui réussira lorsque la condition préalable échoue.
Vous écrivez un test de terminaison en transmettant l’argument processExitsWith à #expect ou #require. Lorsque vous écrivez un test de terminaison, Swift Testing lance un nouveau processus pour exécuter votre test et vous pouvez vérifier que le processus se termine avec succès avec un code ou un signal de sortie spécifique ou avec un état d’échec. Ces bibliothèques à usage général vous permettent d’écrire et de tester du code Swift portable tout au long de votre projet, même au-delà du code de votre app. Chez Apple, nous utilisons Swift dans l’ensemble de notre pile logicielle. Nous l’utilisons pour les micrologiciels, les apps et les frameworks, ainsi que pour les services web à grande échelle. Vous pouvez profiter des améliorations de Swift 6.2 lors de l’écriture de code pour les appareils embarqués, les composants critiques pour la sécurité et les serveurs. Vous pourrez également cibler quelques nouvelles plates-formes. Commençons par le bas de la pile avec Embedded Swift. Embedded Swift est un sous-ensemble de Swift qui vous permet d’écrire du code ciblant les environnements les plus contraints, tels que le programme interne des appareils embarqués et les noyaux de système d’exploitation. Ce mode de compilation prend en charge les principales fonctionnalités de Swift telles que les types de valeurs et de références, les closures, les optionnels, la gestion des erreurs, les génériques, etc. Chez Apple, nous utilisons Embedded Swift dans certains des logiciels de bas niveau sur l’iPhone. Par exemple, dans iOS 26, Embedded Swift s’exécute sur le coprocesseur qui gère l’accès aux pages de mémoire partagée entre le CPU et le GPU. Si vous voulez l’essayer, regardez « Go small with Embedded Swift ». Swift 6.2 enrichit Embedded Swift de nouvelles capacités. Il couvre désormais toutes les API de chaînes de Swift, dont l’interpolation de chaînes. Les types any de Swift, qui peuvent représenter des valeurs de types conformes à un protocole, sont également disponibles chaque fois que le protocole est contraint à des types de classe. InlineArray et Span, deux nouvelles API permettant de travailler efficacement avec les régions de mémoire, sont ajoutées à la bibliothèque standard de Swift. Ces types sont parfaits pour le type de code sensible aux performances que l’on trouve souvent dans les programmes embarqués. Plus Embedded Swift est performant, plus la communauté crée des exemples que vous pouvez utiliser pour démarrer vos propres projets intégrés. Consultez-les sur GitHub dans le dépôt swift-embedded-examples. Embedded Swift vous permet d’écrire des logiciels de bas niveau dans un langage dont la mémoire est sûre par défaut. Le code pour la mémoire est plus sécurisé, et nous essayons d’améliorer encore plus cette sécurité. Parfois, vous devez écrire du code pour effectuer une tâche non sécurisée. Lors de l’intégration avec une dépendance écrite en C, par exemple, il est courant d’utiliser une API qui prend des pointeurs. Dans les contextes critiques en matière de sécurité, le code non sécurisé doit être évité autant que possible. Si c’est inévitable, il doit être facile à identifier. C’est pourquoi nous avons introduit dans Swift 6.2 une nouvelle fonctionnalité *opt-in* appelée Sécurité stricte de la mémoire. Ce mode nécessite que toutes les utilisations d’API non sécurisées soient explicitement reconnues dans le code source. Les annotations requises par ce mode vous aident à identifier les parties de votre code qui nécessitent une attention particulière pour la sécurité. Swift 6.2 prend en charge de nouvelles annotations pour les en-têtes C et C++ qui entraînent l’importation d’API dans Swift à l’aide de types sûrs et ergonomiques comme Span. Pour en savoir plus sur les fonctionnalités d’interopérabilité, consultez « Safely mix C, C++, and Swift ». Dans les systèmes d’exploitation Apple, nous adoptons une sécurité stricte de la mémoire dans deux composants essentiels : WebKit et un sous-système de l’app Messages qui analyse les messages entrants et les pièces jointes. Ces deux composants gèrent les entrées non fiables, il est donc particulièrement important de limiter l’utilisation d’API non sécurisées. Voyons maintenant comment Swift est utilisé dans l’écosystème des serveurs.
Swift joue un rôle important dans les services d’Apple. Chaque seconde, des millions de requêtes sont traitées par des services back-end optimisés par Swift. L’un de ces services est chargé d’alerter les utilisateurs sur les mots de passe corrompus parce qu’ils ont été trouvés dans des fuites de données. Initialement codé en Java, ce service a été réécrit en Swift, et les avantages sont spectaculaires. Grâce au code natif efficace de Swift et à sa gestion déterministe de la mémoire, le débit du service a augmenté de 40 %, tandis que ses exigences matérielles ont été réduites de moitié.
Beaucoup d’entre vous bénéficient de l’adoption de Swift sur le serveur. Par exemple, les ingénieurs de Cultured Code ont réécrit en Swift le backend de l’app Things, appelé Things Cloud, et l’ont décrit sur swift.org.
Pour Things Cloud, l’utilisation de Swift a divisé par 3 les coûts de calcul, tout en améliorant les temps de réponse moyens de 400 %. Autre avantage de l’adoption de Swift : la possibilité d’utiliser le même langage et les mêmes outils pour le développement client et serveur. Les bibliothèques de Swift sont essentielles pour créer des backends de serveur. Swift dispose d’un écosystème de packages en pleine croissance qui couvre un large éventail de cas d’utilisation essentiels. Il existe des bibliothèques pour la mise en réseau, les pilotes de base de données, l’observabilité, le streaming de messages, etc. Une mise à jour notable cette année a été la sortie de la version 2 de gRPC Swift. gRPC est un package moderne et performant pour la création d’API de service. Parmi les points forts de la version 2, citons les API modernisées qui exploitent la concurrence Swift, le code Swift généré idiomatiquement et une couche de transport modulable et performante. La mise à jour de gRPC Swift est détaillée sur le blog de swift.org. Consultez-le pour en savoir plus. L’interopérabilité avec C, Objective-C et C++ est l’un des principaux atouts de Swift. Vous pouvez améliorer progressivement les bases de code existantes écrites dans ces langages en adoptant Swift, un fichier à la fois. Dans l’écosystème serveur, de nombreuses applications existantes sont codées en Java, et c’est le bon moment de les réécrire en Swift. Nous avons annoncé l’année dernière un nouveau projet open source appelé swift-java, qui vise à rendre les langages interopérables de manière transparente.
Avec swift-java, vous pouvez créer des liaisons qui permettent au code Swift d’appeler du code Java et vice versa. Ces liaisons sont conçues pour envelopper les représentations natives des valeurs de chaque langage sans surcharge excessive. Les liaisons Java pour le code Swift peuvent tirer parti de la technologie d’interface étrangère de nouvelle génération de Java ou recourir à JNI si nécessaire. Le projet swift-java est actuellement expérimental et évolue rapidement. Pour en savoir plus sur son fonctionnement, regardez « Explore Swift and Java interoperability ».
Lorsque vous travaillez sur des apps qui ont à la fois des composants client et serveur, vous avez besoin d’un processus capable de tester votre code dans les deux environnements, localement. Apple lance une nouvelle bibliothèque de conteneurisation open source qui vous permet de créer des outils basés sur des conteneurs Linux qui s’exécutent sur votre Mac. La bibliothèque est implémentée en Swift et conçue en mettant l’accent sur la sécurité, la confidentialité et les performances. C’est un excellent exemple d’utilisation de Swift pour le développement au niveau des systèmes. Pour en savoir plus sur cette bibliothèque, regardez « Meet Containerization ». Visitez le dépôt de conteneurisation sur GitHub où vous pouvez trouver des fichiers binaires de ligne de commande pour exécuter des conteneurs. Voici quelques mises à jour sur les plates-formes prises en charge par Swift. Swift 6.2 ajoute la prise en charge officielle de FreeBSD, un OS populaire sur les serveurs et les plates-formes embarquées. De plus, Swift prend en charge WebAssembly, connu sous le nom de Wasm. WebAssembly est une plate-forme de machine virtuelle axée sur la portabilité, la sécurité et les hautes performances. Les développeurs peuvent créer des applications client et serveur pour Wasm, puis les déployer sur le navigateur ou d’autres environnements d’exécution. Le support WebAssembly a commencé comme un projet communautaire. Plus tôt cette année, ce projet a franchi une étape importante avec un document de vision pour la prise en charge officielle de WebAssembly en Swift. Voyons le support Wasm en action. J’ai une app écrite en Swift qui charge un modèle 3D à partir d’un fichier et l’affiche ensuite dans le navigateur. Voici à quoi ressemble l’app en ce moment.
L’app s’exécute sur la machine virtuelle Wasm, et le logo Swift est rendu à l’aide d’une norme web expérimentale appelée WebGPU.
L’app utilise JavascriptKit, un paquet open source développé par l’organisation SwiftWasm. Je peux utiliser cette bibliothèque pour interagir avec le runtime Javascript via les API Swift natives. Pour rendre le binaire final aussi compact que possible, je compile l’app avec Embedded Swift, mais ce code est essentiellement du Swift normal.
Par exemple, j’ai ajouté des utilitaires de géométrie qui exploitent des génériques. Mon analyseur pour les fichiers objets Wavefront utilise les API String natives de Swift.
Ajoutons un peu d’animation. Examinons la méthode de mise à jour de notre moteur de rendu.
Pour faire tourner le modèle, la rotation du logo doit être mise à jour sur chaque image.
Testons-le. Pour réexécuter l’application, j’ai déclenché une tâche à partir du panneau Project. La tâche est configurée pour appeler Swift Build afin de compiler l’app Wasm. Elle rend ensuite le binaire aussi petit que possible en exécutant quelques outils de minimisation sur la sortie de la compilation. Enfin, elle démarre un serveur web pour héberger le contenu. Ça a l’air génial. Swift est un excellent langage et représente donc un bon choix dans toute la pile logicielle. Swift privilégie la sécurité et la facilité d’utilisation, tout en fournissant aux programmeurs avancés des outils pour écrire du code complexe et l’ajuster pour obtenir des performances maximales. Vous pouvez vous familiariser avec les fonctionnalités du langage selon vos besoins. Vous pouvez commencer petit et approfondir les fonctionnalités avancées lorsque vous le souhaitez.
Swift 6.2 fait évoluer le langage pour le rendre plus facile, aussi bien pour les débutants que pour les experts. Nous avons fourni un chemin plus accessible pour introduire la concurrence dans un projet. Nous avons adapté ce langage aux experts qui rédigent du code critique pour les performances. Commençons par les mises à jour des performances. Le type Array est une liste ordonnée d’éléments, et c’est l’un des types de données les plus utilisés dans les projets Swift. Les fonctionnalités d’Array, telles que le redimensionnement dynamique, le rendent adapté à de nombreuses tâches. Cette flexibilité a un coût. Pour prendre en charge le redimensionnement dynamique, un tableau stocke une référence à un tampon alloué sur le tas. Lorsque d’autres éléments sont ajoutés et que le tableau est à pleine capacité, la nouvelle mémoire doit être allouée dynamiquement et les éléments existants sont copiés. Si vous profilez du code critique pour les performances qui utilise Array dans une section sollicitée, vous remarquerez peut-être une allocation de mémoire ou un comptage de références pour le tampon de tableau que vous devez éliminer. Si la taille d’un tableau ne change jamais, il n’est pas nécessaire de payer le coût de l’allocation sur le tas. Inline Array est un nouveau type de tableau à taille fixe avec un stockage en ligne pour ses éléments. La taille fait partie du type, écrite entre crochets avant le type d’élément.
Au lieu de stocker une référence à un tampon contenant les éléments, les éléments d’un InlineArray sont stockés directement. Cela signifie que les éléments peuvent être stockés sur la pile ou directement dans d’autres types sans allocation supplémentaire sur le tas. Les InlineArrays peuvent stocker des types copiables et non copiables. Lors du stockage de types copiables, l’InlineArray lui-même peut être copié et les valeurs des éléments sont copiées. L’écriture de la taille en tant que partie du type est réalisée à l’aide d’une nouvelle fonctionnalité des génériques qui permet d’utiliser des entiers comme paramètres de type. Tout comme le type d’élément, la taille d’un InlineArray peut être déduite d’un littéral de tableau. Si vous écrivez un tableau inline contenant 1, 2 et 3, le type est automatiquement inféré comme un InlineArray de 3 entiers. Connaître la taille d’un InlineArray au moment de la compilation permet également d’effectuer d’autres optimisations, comme l’élimination de la vérification des limites lorsque l’index est inférieur à la taille. Un type de conteneur doit souvent fournir un accès direct à son stockage sous-jacent. Ceci est utile pour effectuer un traitement local sur une mémoire contiguë sans avoir besoin de connaître la disposition du conteneur d’origine. Par exemple, une fonction peut vouloir permettre d’opérer directement sur le stockage contigu d’un Array ou d’un InlineArray. Avant Swift 6.2, la solution courante consistait à recourir aux pointeurs non sécurisés, qui sont efficaces, mais non sécurisés et sujets aux erreurs.
Le nouveau type Span est une abstraction qui fournit un accès rapide et direct à la mémoire contiguë sans compromettre la sécurité de la mémoire. La bibliothèque standard fournit une propriété span pour tous les types de conteneurs qui disposent d’un stockage contigu pour leurs éléments, y compris Array, ArraySlice, InlineArray, etc.
Lorsque vous utilisez Span, il maintient la sécurité de la mémoire en s’assurant que la mémoire contiguë reste valide. Ces garanties éliminent les problèmes de sécurité de la mémoire inhérents aux pointeurs, y compris l’utilisation après libération et les modifications concurrentes. Ils sont vérifiés au moment de la compilation sans surcharge d’exécution. Par exemple, la modification du conteneur d’origine empêchera l’accès à la span par la suite. Après la modification, vous ne pouvez plus accéder à la variable span.
Une span ne peut pas non plus survivre au conteneur d’origine. C’est ce qu’on appelle une dépendance à durée de vie et cela empêche le stockage sous-jacent d’être détruit alors qu’il est toujours accessible par le span. Pour de nouvelles façons de contrôler les performances avec InlineArray et Span, regardez « Improve memory usage and performance with Swift ». Pour en savoir plus sur les caractéristiques de performances de votre code Swift, consultez « Explore Swift performance ».
Un autre aspect de la performance est la réactivité, lorsqu’un programme doit effectuer plusieurs tâches en même temps. La programmation concurrente est difficile, car le partage de la mémoire entre plusieurs tâches est sujet à des erreurs et à un comportement imprévisible. La sécurité Data-ray de Swift 6 empêche ces erreurs au moment de la compilation, ce qui vous permet d’écrire du code concurrent sans craindre d’introduire des bogues d’exécution difficiles à éliminer. Mais souvent, le code le plus naturel à écrire est sujet à la concurrence, ce qui entraîne des erreurs de compilation à corriger. Une classe avec un état mutable, comme PhotoProcessor, est sûre tant que vous n’y accédez pas de manière concurrente. Elle dispose d’une méthode asynchrone pour extraire un autocollant en calculant le sujet des données d’image fournies. Si vous essayez d’appeler extractSticker à partir du code de la UI sur main actor, vous obtiendrez une erreur indiquant que l’appel risque de provoquer des conditions de concurrence. En effet, il y a plusieurs endroits dans le langage qui déchargent implicitement le travail en arrière-plan, même si vous n’avez jamais eu besoin que le code s’exécute en parallèle.
Swift 6.2 modifie cette philosophie pour rester monothread par défaut jusqu’à ce que vous choisissiez d’introduire la concurrence.
Les changements de langage dans Swift 6.2 rendent le code le plus naturel pour écrire des données sans concurrence par défaut. Ceci fournit un chemin plus accessible pour introduire la concurrence dans un projet. Lorsque vous choisissez d’introduire la concurrence pour exécuter du code en parallèle, la sécurité contre la concurrence des données vous protège. Tout d’abord, nous avons simplifié l’appel de fonctions asynchrones sur des types à état mutable. Au lieu de décharger immédiatement les fonctions asynchrones qui ne sont pas liées à un acteur spécifique, la fonction continue de s’exécuter sur l’acteur à partir duquel elle a été appelée. Cela élimine les conditions de concurrence, car les valeurs transmises à la fonction asynchrone ne sont jamais envoyées en dehors de l’acteur. Les fonctions asynchrones peuvent toujours se décharger du travail dans leur implémentation, mais les clients n’ont pas à se soucier de leur état mutable.
Nous avons simplifié la mise en œuvre des conformités sur les types liés au main actor. Ici, j’ai un protocole appelé Exportable, et j’essaie d’implémenter une conformité pour ma classe StickerModel du main actor. L’exigence export n’a pas d’isolation d’acteur, donc le langage supposait qu’elle pouvait être appelée en dehors du main actor et empêchait StickerModel d’utiliser l’état du main actor dans son implémentation.
Swift 6.2 prend en charge ces conformités. Une conformité qui nécessite l’état du main actor est appelée une conformité *isolée*. Ceci est sûr, car le compilateur garantit qu’une conformité au main actor n’est utilisée que sur le main actor. Je peux créer un type ImageExporter qui ajoute un StickerModel à un tableau de n’importe quel élément exportable tant qu’il reste sur le main actor. Si j’autorise l’utilisation d’ImageExporter de n’importe où, le compilateur empêche l’ajout de StickerModel au tableau, car il n’est pas sûr d’appeler export sur StickerModel en dehors du main actor. Avec des conformités isolées, vous n’avez à résoudre les problèmes de sécurité de conditions de concurrence que lorsque le code indique qu’il utilise la conformité de manière concurrente.
Les variables globales et statiques sont sujettes aux conditions de concurrence, car elles permettent d’accéder à l’état mutable de n’importe où.
La façon la plus courante de protéger l’état global est avec le main actor. Et il est courant d’annoter une classe entière avec le main actor pour protéger tout son état mutable, en particulier dans un projet qui n’a pas beaucoup de tâches concurrentes. Vous pouvez modéliser un programme entièrement monothread en appliquant @MainActor à tous les éléments dans votre projet. Pour faciliter la modélisation du code monothread, nous avons introduit un mode qui infère le main actor par défaut. Cela élimine les erreurs de sécurité data-ray sur les variables globales et statiques non sécurisées, les appels à d’autres fonctions du main actor comme celles du SDK, et plus encore, car le main actor protège tout l’état mutable par défaut. Il réduit également les annotations de concurrence dans le code qui est principalement monothread. Ce mode est idéal pour les projets qui font la plupart du travail sur le main actor et où le code concurrent est encapsulé dans des types ou des fichiers spécifiques. Il est recommandé pour les apps, les scripts et autres cibles exécutables. Le transfert du travail en arrière-plan reste important pour les performances, par exemple, pour assurer la réactivité des apps lors de tâches intensives en CPU. Regardons l’implémentation de la méthode extractSticker sur PhotoProcessor. Il vérifie d’abord s’il a déjà extrait un autocollant pour une image, afin de pouvoir renvoyer immédiatement l’autocollant mis en cache. Si l’autocollant n’a pas été mis en cache, il extrait le sujet des données de l’image et crée un nouvel autocollant. La méthode extractSubject effectue un traitement d’image coûteux indésirable pour bloquer le main actor ou tout autre acteur. Je peux me décharger de ce travail en utilisant l’attribut @concurrent. @concurrent garantit qu’une fonction s’exécute toujours sur le pool de threads concurrent, ce qui permet à l’acteur d’exécuter d’autres tâches en même temps. Ces changements de langage fonctionnent ensemble pour rendre la concurrence plus accessible. Vous commencez par écrire du code qui s’exécute par défaut sur le main actor, où il n’y a aucun risque de conditions de concurrence. Lorsque vous utilisez des fonctions asynchrones, celles-ci s’exécutent de l’endroit où elles sont appelées. Il n’y a toujours aucun risque de conditions de concurrence, car tout votre code fonctionne toujours sur le main actor. Lorsque vous êtes prêt à adopter la concurrence pour améliorer les performances, il est facile de transférer du code spécifique en arrière-plan pour l’exécuter en parallèle. Pour en savoir plus sur l’utilisation de la concurrence dans la pratique, consultez « Elevate an App with Swift concurrency ». Pour en savoir plus sur les concepts fondamentaux de la concurrence, regardez « Embracing Swift Concurrency ». Certains de ces changements de langage sont facultatifs, car ils nécessitent des changements dans votre projet pour être adoptés. Vous pouvez rechercher et activer tous les changements de langage de concurrence dans la section Swift Compiler - Concurrency des réglages de build d’Xcode. Vous pouvez également activer ces fonctionnalités dans un fichier manifeste de package Swift à l’aide de l’API SwiftSettings. Swift 6.2 comprend des outils de migration qui vous aident à effectuer automatiquement les modifications de code nécessaires. Pour en savoir plus sur les outils de migration, consultez swift.org/migration. Ces améliorations de la concurrence ont été façonnées par vos commentaires sur l’adoption de la sécurité des données dans vos projets. Que vous signaliez un bogue, que vous posiez une question sur une erreur de concurrence que vous ne comprenez pas, que vous examiniez une proposition d’évolution sur les forums ou que vous rédigiez vous-même des changements de langue, votre contribution fait la différence. Merci de contribuer à rendre la concurrence plus accessible à tous. Si vous voulez participer à l’amélioration de Swift, rejoignez-nous sur les forums de swift.org. Tout le monde est invité à participer à la promotion du langage et de l’écosystème, n’hésitez pas à partager vos propres projets dans la section vitrine communautaire. Grâce aux forums, vous pouvez rester à jour de tout ce qui se passe chez Swift : conférences, réunions, réseaux sociaux, etc. Merci de votre participation aujourd’hui, et à bientôt sur les forums.
-
-
9:44 - Subprocess: Call `run` with string
import Subprocess let result = try await run( .name("pwd") )
-
10:04 - Subprocess: Call `run` with file path
import Subprocess let swiftPath = FilePath("/usr/bin/swift") let result = try await run( .path(swiftPath), arguments: ["--version"] )
-
10:05 - Subprocess: Accessing standard output
import Subprocess let swiftPath = FilePath("/usr/bin/swift") let result = try await run( .path(swiftPath), arguments: ["--version"] ) let swiftVersion = result.standardOutput
-
10:51 - NotificationCenter: Dynamic types
import UIKit @MainActor class KeyboardObserver { func registerObserver(screen: UIScreen) { let center = NotificationCenter.default let token = center.addObserver( forName: UIResponder.keyboardWillShowNotification, object: screen, queue: .main ) { notification in guard let userInfo = notification.userInfo else { return } let startFrame = userInfo[UIResponder.keyboardFrameBeginUserInfoKey] as? CGRect let endFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect guard let startFrame, let endFrame else { return } self.keyboardWillShow(startFrame: startFrame, endFrame: endFrame) } } func keyboardWillShow(startFrame: CGRect, endFrame: CGRect) {} }
-
11:34 - NotificationCenter: Concrete types
import UIKit @MainActor class KeyboardObserver { func registerObserver(screen: UIScreen) { let center = NotificationCenter.default let token = center.addObserver( of: screen, for: .keyboardWillShow ) { keyboardState in let startFrame = keyboardState.startFrame let endFrame = keyboardState.endFrame self.keyboardWillShow(startFrame: startFrame, endFrame: endFrame) } } func keyboardWillShow(startFrame: CGRect, endFrame: CGRect) {} }
-
12:01 - NotificationCenter: Conformances
extension UIResponder { public struct KeyboardWillShowMessage: NotificationCenter.MainActorMessage } extension HTTPCookieStorage { public struct CookiesChangedMessage: NotificationCenter.AsyncMessage }
-
12:48 - Observation: The @Observable macro
import Observation enum Item { case none case banana case star } @Observable class Player { let name: String var score: Int = 0 var item: Item = .none init(name: String) { self.name = name } }
-
12:58 - Observation: The Observations type
import Observation enum Item { case none case banana case star } @Observable class Player { let name: String var score: Int = 0 var item: Item = .none init(name: String) { self.name = name } } let player = Player(name: "Holly") let values = Observations { let score = "\(player.score) points" let item = switch player.item { case .none: "no item" case .banana: "a banana" case .star: "a star" } return "\(score) and \(item)" }
-
13:56 - Observation: Transactional updates
import Observation enum Item { case none case banana case star } @Observable class Player { let name: String var score: Int = 0 var item: Item = .none init(name: String) { self.name = name } } let player = Player(name: "Holly") let values = Observations { let score = "\(player.score) points" let item = switch player.item { case .none: "no item" case .banana: "a banana" case .star: "a star" } return "\(score) and \(item)" } player.score += 2 player.item = .banana
-
14:05 - Observation: AsyncSequence
import Observation enum Item { case none case banana case star } @Observable class Player { let name: String var score: Int = 0 var item: Item = .none init(name: String) { self.name = name } } let player = Player(name: "Holly") let values = Observations { let score = "\(player.score) points" let item = switch player.item { case .none: "no item" case .banana: "a banana" case .star: "a star" } return "\(score) and \(item)" } player.score += 2 player.item = .banana for await value in values { print(value) }
-
14:17 - Swift Testing
import Testing import Foundation import EvolutionMetadataModel @Test func validateProposalID() async throws { let (data, _) = try await URLSession.shared.data(from: evolutionJSONMetadataURL) let jsonDecoder = JSONDecoder() let metadata = try jsonDecoder.decode(EvolutionMetadata.self, from: data) for proposal in metadata.proposals { #expect(proposal.id.starts(with: "SE")) } }
-
14:54 - Swift Testing: Attachments
import Testing import Foundation import EvolutionMetadataModel @Test func validateProposalID() async throws { let (data, _) = try await URLSession.shared.data(from: evolutionJSONMetadataURL) Attachment.record(data, named: "evolution-metadata.json") let jsonDecoder = JSONDecoder() let metadata = try jsonDecoder.decode(EvolutionMetadata.self, from: data) for proposal in metadata.proposals { #expect(proposal.id.starts(with: "SE")) } }
-
15:23 - Exit Tests: Preconditions
extension Proposal { public var number: Int { let components = id.split(separator: "-") precondition( components.count == 2 && components[1].allSatisfy(\.isNumber), "Invalid proposal ID format \(id); expected SE-<Number>" ) return Int(components[1])! } }
-
15:34 - Exit Tests: processExitsWith argument
import Testing import EvolutionMetadataModel @Test func invalidProposalPrefix() async throws { await #expect(processExitsWith: .failure) { let proposal = Proposal(id: "SE-NNNN") _ = proposal.number } }
-
31:06 - Concurrency: Async function error message
class PhotoProcessor { func extractSticker(data: Data, with id: String?) async -> Sticker? { } } @MainActor final class StickerModel { let photoProcessor = PhotoProcessor() func extractSticker(_ item: PhotosPickerItem) async throws -> Sticker? { guard let data = try await item.loadTransferable(type: Data.self) else { return nil } return await photoProcessor.extractSticker(data: data, with: item.itemIdentifier) } }
-
32:06 - Concurrency: Run async functions on the caller's actor
// Run async functions on the caller's actor class PhotoProcessor { func extractSticker(data: Data, with id: String?) async -> Sticker? {} } @MainActor final class StickerModel { let photoProcessor = PhotoProcessor() func extractSticker(_ item: PhotosPickerItem) async throws -> Sticker? { guard let data = try await item.loadTransferable(type: Data.self) else { return nil } return await photoProcessor.extractSticker(data: data, with: item.itemIdentifier) } }
-
32:36 - Concurrency: Conformance error
protocol Exportable { func export() } extension StickerModel: Exportable { // error: Conformance of 'StickerModel' to protocol 'Exportable' crosses into main actor-isolated code and can cause data races func export() { photoProcessor.exportAsPNG() } }
-
33:04 - Concurrency: Isolated conformances
// Isolated conformances protocol Exportable { func export() } extension StickerModel: @MainActor Exportable { func export() { photoProcessor.exportAsPNG() } }
-
33:20 - Concurrency: Isolated conformance use
// Isolated conformances @MainActor struct ImageExporter { var items: [any Exportable] mutating func add(_ item: StickerModel) { items.append(item) } func exportAll() { for item in items { item.export() } } }
-
33:31 - Concurrency: Isolated conformance error
// Isolated conformances nonisolated struct ImageExporter { var items: [any Exportable] mutating func add(_ item: StickerModel) { items.append(item) // error: Main actor-isolated conformance of 'StickerModel' to 'Exportable' cannot be used in nonisolated context } func exportAll() { for item in items { item.export() } } }
-
33:51 - Concurrency: Unsafe static variable
final class StickerLibrary { static let shared: StickerLibrary = .init() // error: Static property 'shared' is not concurrency-safe because non-'Sendable' type 'StickerLibrary' may have shared mutable state }
-
34:01 - Concurrency: Protecting static variables
final class StickerLibrary { @MainActor static let shared: StickerLibrary = .init() }
-
34:05 - Concurrency: Protecting classes
@MainActor final class StickerLibrary { static let shared: StickerLibrary = .init() }
-
34:15 - Concurrency: A single-threaded program
@MainActor final class StickerLibrary { static let shared: StickerLibrary = .init() } @MainActor final class StickerModel { let photoProcessor: PhotoProcessor var selection: [PhotosPickerItem] } extension StickerModel: @MainActor Exportable { func export() { photoProcessor.exportAsPNG() } }
-
34:22 - Concurrency: Mode to infer main actor by default
// Mode to infer main actor by default final class StickerLibrary { static let shared: StickerLibrary = .init() } final class StickerModel { let photoProcessor: PhotoProcessor var selection: [PhotosPickerItem] } extension StickerModel: Exportable { func export() { photoProcessor.exportAsPNG() } }
-
35:06 - Concurrency: Explicitly offloading async work
// Explicitly offloading async work class PhotoProcessor { var cachedStickers: [String: Sticker] func extractSticker(data: Data, with id: String) async -> Sticker { if let sticker = cachedStickers[id] { return sticker } let sticker = await Self.extractSubject(from: data) cachedStickers[id] = sticker return sticker } @concurrent static func extractSubject(from data: Data) async -> Sticker {} }
-
-
- 0:00 - Introduction et ordre du jour
Découvrez les nouveautés de Swift 6.2. Parmi les points forts : améliorations des processus, nouvelles API de bibliothèque, adoption étendue de la pile logicielle et fonctionnalités de langage améliorées pour la gestion de la simultanéité pour un codage plus productif.
- 0:48 - Mises à jour de swiftlang
L’organisation swiftlang sur GitHub s’est considérablement développée, englobant plus de 50 projets, dont le compilateur Swift, le système de build de Xcode Swift Build et le site web Swift.org. Swift Build, désormais en open source, prend en charge le processus de compilation pour les systèmes d’exploitation Apple et est utilisé par Swift Package Manager. Un nouveau gestionnaire de versions, Swiftly, développé à l’origine pour Linux, prend désormais en charge macOS et simplifie la gestion de la chaîne d’outils Swift. La page d’accueil Swift.org a un nouveau look pour vous aider dans différents domaines.
- 3:06 - Workflow de développement : Écriture de code
La dernière version Swift améliore les flux de développement sur toutes les plateformes, avec des améliorations spécifiques pour les utilisateurs de l’extension Swift dans VS Code, notamment une validation officielle et une distribution par Swift.org. Désormais, l’indexation en arrière-plan permet des fonctionnalités en temps réel dans l’éditeur, la saisie semi-automatique du code est améliorée, le débogage est simplifié grâce à la prise en charge automatique de LLDB, et un nouveau panneau de projet ainsi que des aperçus en direct de DocC sont disponibles.
- 4:40 - Workflow de développement : Création
Swift 6.2 introduit plusieurs améliorations pour renforcer votre productivité. Les temps de compilation à neuf pour les projets utilisant des API basées sur des macros sont améliorés, car la bibliothèque swift-syntax n’a plus besoin d’être reconstruite lors des builds à neuf. Cette optimisation, prise en charge par Swift PM et Xcode, peut réduire les temps de compilation de plusieurs minutes. Cette version améliore aussi la documentation des diagnostics du compilateur en fournissant des explications plus détaillées sur les avertissements et erreurs courants, ce qui les rend plus faciles à comprendre et à corriger. Vous disposez désormais d’un contrôle accru sur les avertissements du compilateur : vous pouvez spécifier ceux à traiter comme des erreurs, une fonctionnalité issue des retours de la communauté.
- 7:36 - Workflow de développement : Débogage
Le débogage est amélioré dans Swift 6.2, en particulier pour le code asynchrone, avec des fonctionnalités LLDB améliorées, la possibilité de nommer les tâches et à une visibilité accrue dans les profils Instruments. Les temps de réponse du débogueur sont également plus rapides, grâce aux modules explicitement compilés activés par défaut dans Xcode 26.
- 9:14 - Bibliothèques : Sous-processus
Cette version introduit le nouveau package Subprocess, avec lequel vous pouvez lancer et gérer des sous-processus directement à partir du code Swift. Le package vous donne un contrôle précis sur l’exécution des processus, vous permettant de spécifier le chemin de l’exécutable. Lorsque le sous-processus se termine, vous pouvez inspecter l’état de sortie, la sortie standard et d’autres infos sur l’exécution du processus, la version 0.1 étant désormais disponible et ouverte aux commentaires.
- 10:45 - Bibliothèques : Foundation
Le groupe de travail Foundation a amélioré le développement d’apps iOS en introduisant des types concrets pour les noms et les charges utiles des notifications, ce qui simplifie le code, réduit les erreurs et renforce la sécurité des threads, pour les notifications du framework comme pour les notifications personnalisées. Vous pouvez également définir des types de notification concrets pour vos propres notifications.
- 12:31 - Bibliothèques : Observation
La bibliothèque Observation de Swift utilise le modèle d’observateur pour suivre les changements d’état dans un graphe d’objets. La macro Observable permet d’activer le suivi des observations. Swift 6.2 introduit le type Observations, qui permet de créer une AsyncSequence diffusant les changements d’état à partir d’une fermeture calculant une valeur à partir de propriétés observables. Les mises à jour sont transactionnelles, garantissant un état cohérent, et peuvent être parcourues à l’aide d’une boucle for await.
- 14:13 - Bibliothèques : Test
Avec Swift Testing, une bibliothèque multiplateforme, vous pouvez écrire et organiser vos tests à l’aide de macros. Swift 6.2 renforce cette capacité avec des pièces jointes personnalisées pour un meilleur diagnostic des pannes, notamment en environnement distant, et des tests de sortie pour valider le code qui se termine dans des conditions spécifiques. Ces fonctionnalités permettent de tester du code Swift portable, au-delà du simple code de votre application.
- 16:08 - Swift à tous les niveaux : Swift embarqué
Swift 6.2 améliore Embedded Swift, en vous permettant d’écrire du code pour des appareils embarqués, des serveurs et des composants critiques en matière de sécurité. Il inclut désormais les API complètes pour les chaînes de caractères, les types any de Swift pour les protocoles contraints aux classes, ainsi que de nouvelles API comme InlineArray et Span pour travailler efficacement avec les régions de mémoire. Apple utilise Embedded Swift dans certains des logiciels de bas niveau sur l’iPhone, et la communauté propose des exemples disponibles sur GitHub, dans le dépôt swift-embedded-examples.
- 18:00 - Swift à tous les niveaux : Sécurité
Swift 6.2 introduit le mode strict-memory-safety, activable manuellement, qui exige une validation explicite des API non sûres et aide à repérer le code sensible sur le plan de la sécurité. Apple adopte ce mode dans WebKit et dans un sous-système de l’app Messages, tous deux exposés à des données non fiables.
- 19:37 - Swift à tous les niveaux : Serveur
Swift est largement utilisé dans l’écosystème des serveurs, en particulier chez Apple, où il alimente les services backend traitant des millions de requêtes par seconde. Un exemple notable est un service d’alerte par mot de passe, auparavant développé en Java, qui a connu une augmentation de 40 % du débit et une réduction de 50 % des besoins matériels après avoir été réécrit en Swift. D’autres entreprises, comme Cultured Code, ont également tiré des bénéfices de l’adoption de Swift. Le backend de Things Cloud, réécrit en Swift, a permis de diviser par 3 les coûts de calcul et d’améliorer les temps de réponse moyens de 400 %. L’écosystème de packages de Swift, son interopérabilité avec C, Objective-C et C++, ainsi que les nouveaux projets open source comme Swift-Java et une bibliothèque de conteneurisation, permettent aux développeurs de créer des serveurs backends efficaces et performants, et d’intégrer de manière transparente Swift aux bases de code existantes, en particulier en Java.
- 23:23 - Swift à tous les niveaux : Plates-formes
Swift 6.2 prend officiellement en charge FreeBSD et WebAssembly (Wasm), ce qui permet de créer des applications client et serveur pour les navigateurs et d’autres environnements d’exécution. Cette prise en charge, née d’un projet communautaire, permet de compiler du code Swift et de l’exécuter dans le navigateur, comme le montre une app de rendu 3D utilisant WebGPU et JavaScriptKit. Grâce à sa sécurité, sa simplicité d’usage et ses performances, Swift s’impose comme un choix attractif dans toute la pile logicielle.
- 26:11 - Évolution du langage : Performances
La nouvelle version introduit également 2 nouveaux types, InlineArray et Span, pour améliorer les performances du code critique. InlineArray est un tableau de taille fixe qui stocke directement ses éléments, supprimant ainsi le recours à une allocation sur le tas. Cela améliore les performances, notamment dans les chemins critiques, et permet d’autres optimisations, comme l’élimination de la vérification des limites. Le système définit la taille d’un InlineArray comme faisant partie de son type, et peut la déduire à partir de littéraux de tableau. Span offre un accès rapide et direct à une mémoire contiguë, sans compromettre la sécurité mémoire. Il permet aux fonctions d’opérer efficacement et en toute sécurité sur le stockage sous-jacent de différents types de conteneurs, comme Array et InlineArray. Grâce à des vérifications effectuées à la compilation, Span garantit la validité de la mémoire et évite les problèmes courants inhérents aux pointeurs.
- 30:28 - Évolution du langage : Concurrence
La simultanéité est un aspect complexe de la programmation, en raison du risque de conflits d’accès aux données lorsque plusieurs tâches partagent la mémoire. Swift 6 a introduit la sécurité contre les conflits d’accès dès la compilation, mais cela entraînait souvent des erreurs du compilateur, car le langage déléguait implicitement certaines opérations en arrière-plan, même lorsque l’exécution parallèle n’était pas nécessaire. Swift 6.2 corrige ce problème en adoptant une nouvelle approche par défaut : le code reste monothread jusqu’à ce que vous choisissiez d’introduire la simultanéité. Cette approche permet, par défaut, d’écrire du code naturellement exempt de conflits d’accès aux données. Le langage permet désormais aux fonctions async non liées à un acteur spécifique de se poursuivre dans le même acteur que celui depuis lequel elles ont été appelées, éliminant ainsi les conflits d’accès aux données. Cette version introduit également des conformités isolées, permettant aux types d’acteurs principaux de se conformer aux protocoles tout en garantissant que le compilateur protège l’état de l’acteur principal. De plus, il existe désormais un mode opt-in pour déduire l’acteur principal par défaut, réduisant ainsi les annotations de simultanéité dans le code monothread. Si vous avez besoin de simultanéité pour améliorer les performances (pour décharger les tâches gourmandes en ressources CPU en arrière-plan), Swift 6.2 fournit des outils pour le faire en toute sécurité. L’attribut concurrent garantit que certaines fonctions s’exécutent dans le pool de threads concurrents, libérant ainsi l’acteur actuel pour exécuter d’autres tâches en parallèle. Ces changements contribuent à rendre la simultanéité plus accessible et plus facile à mettre en œuvre dans les projets Swift.
- 37:15 - Conclusion
Les retours des utilisateurs ont permis d’améliorer la gestion de la simultanéité dans Swift, la rendant plus intuitive et conviviale. La communauté est invitée à participer aux forums de Swift.org pour contribuer au développement du langage et de son écosystème, partager ses projets et rester informée des évènements liés à Swift.