Article de reference

Swift (langage de programmation)

Swift est un langage de programmation compilé de haut niveau , à usage général et multi-paradigme , créé par Chris Lattner en 2010 pour Apple Inc. et maintenu par la communauté ...

Swift est un langage de programmation compilé de haut niveau , à usage général et multi-paradigme , créé par Chris Lattner en 2010 pour Apple Inc. et maintenu par la communauté open source . Swift compile en code machine et utilise un compilateur basé sur LLVM . Swift a été publié pour la première fois en juin 2014 et la chaîne d'outils Swift est livrée dans Xcode depuis la version 6 de Xcode, publiée en septembre 2014.

Apple a voulu que Swift prenne en charge de nombreux concepts de base associés à Objective-C , notamment la répartition dynamique , la liaison tardive généralisée , la programmation extensible et des fonctionnalités similaires, mais d'une manière plus « sûre », facilitant la détection des bogues logiciels . Swift dispose de fonctionnalités permettant de corriger certaines erreurs de programmation courantes comme le déréférencement de pointeur nul et fournit du sucre syntaxique pour éviter la pyramide de la mort . Swift prend en charge le concept d' extensibilité de protocole , un système d'extensibilité qui peut être appliqué aux types, aux structures et aux classes , qu'Apple promeut comme un véritable changement dans les paradigmes de programmation qu'ils qualifient de « programmation orientée protocole » (similaire aux traits et aux classes de types ).

Swift a été présenté à la Worldwide Developers Conference (WWDC) d'Apple en 2014. Il a subi une mise à niveau vers la version 1.2 en 2014 et une mise à niveau majeure vers Swift 2 à la WWDC 2015. Il s'agissait initialement d'un langage propriétaire , mais la version 2.2 est devenue un logiciel open source sous la licence Apache 2.0 le 3 décembre 2015, pour les plateformes d'Apple et Linux .

Au cours de la version 3.0, la syntaxe de Swift a connu une évolution significative, l'équipe principale faisant de la stabilité de la source une priorité dans les versions ultérieures. Au premier trimestre 2018, Swift a dépassé Objective-C en termes de popularité mesurée.

Swift 4.0, sorti en 2017, a introduit plusieurs modifications dans certaines classes et structures intégrées. Le code écrit avec les versions précédentes de Swift peut être mis à jour à l'aide de la fonctionnalité de migration intégrée à Xcode. Swift 5, sorti en mars 2019, a introduit une interface binaire stable sur les plateformes Apple, permettant à l'environnement d'exécution Swift d'être intégré aux systèmes d'exploitation Apple. Il est compatible avec Swift 4.

Swift 5.1 a été officiellement publié en septembre 2019. Swift 5.1 s'appuie sur la version précédente de Swift 5 en étendant les fonctionnalités stables du langage au moment de la compilation avec l'introduction de la stabilité des modules. L'introduction de la stabilité des modules permet de créer et de partager des frameworks binaires qui fonctionneront avec les futures versions de Swift.

Swift 5.5, annoncé officiellement par Apple lors de la WWDC 2021 , étend considérablement la prise en charge du langage pour la concurrence et le code asynchrone , en introduisant notamment une version unique du modèle d'acteur .

Swift 5.9 est sorti en septembre 2023 et comprend un système de macros, des packs de paramètres génériques et des fonctionnalités de propriété comme le nouvel consumeopérateur.

Swift 5.10 est sorti en mars 2024. Cette version améliore le modèle de concurrence du langage, permettant une isolation complète des données pour éviter les conflits de données . C'est également la dernière version avant Swift 6. La version 5.10 est actuellement disponible pour macOS, Windows et Linux.

Swift 6 est sorti en septembre 2024.

Histoire

Le développement de Swift a commencé en juillet 2010 par Chris Lattner , avec la collaboration éventuelle de nombreux autres programmeurs d' Apple . Swift a été motivé par le besoin d'un remplacement pour le langage de programmation Objective-C d'Apple , qui était resté en grande partie inchangé depuis le début des années 1980 et manquait de fonctionnalités de langage modernes. Swift a pris des idées de langage « d' Objective-C , Rust , Haskell , Ruby , Python , C# , CLU et bien trop d'autres pour être listés ». Le 2 juin 2014, l' application Apple Worldwide Developers Conference (WWDC) est devenue la première application publiée publiquement écrite avec Swift. Une version bêta du langage de programmation a été publiée pour les développeurs Apple inscrits à la conférence, mais la société n'a pas promis que la version finale de Swift serait compatible avec le code source de la version de test. Apple prévoyait de mettre à disposition des convertisseurs de code source si nécessaire pour la version complète.

Le langage de programmation Swift , un manuel gratuit de 500 pages, a également été publié à la WWDC et est disponible sur l' Apple Books Store et sur le site officiel.

Swift a atteint le cap 1.0 le 9 septembre 2014, avec le Gold Master de Xcode 6.0 pour iOS . Swift 1.1 est sorti le 22 octobre 2014, parallèlement au lancement de Xcode 6.1. Swift 1.2 est sorti le 8 avril 2015, en même temps que Xcode 6.3. Swift 2.0 a été annoncé à la WWDC 2015 et a été mis à disposition pour la publication d'applications dans l'App Store le 21 septembre 2015. Swift 3.0 est sorti le 13 septembre 2016. Swift 4.0 est sorti le 19 septembre 2017. Swift 4.1 est sorti le 29 mars 2018.

Swift a remporté la première place du langage de programmation le plus apprécié dans l' enquête Stack Overflow Developer Survey 2015 et la deuxième place en 2016.

Le 3 décembre 2015, le langage Swift, les bibliothèques de support, le débogueur et le gestionnaire de paquets ont été rendus open source sous la licence Apache 2.0 avec une exception de bibliothèque d'exécution, et Swift.org a été créé pour héberger le projet. Le code source est hébergé sur GitHub, où il est facile pour quiconque d'obtenir le code, de le créer lui-même et même de créer des demandes d'extraction pour contribuer au code du projet.

En décembre 2015, IBM a annoncé son site Web Swift Sandbox, qui permet aux développeurs d'écrire du code Swift dans un volet et d'afficher la sortie dans un autre. Swift Sandbox est devenu obsolète en janvier 2018.

Lors de la WWDC 2016 , Apple a annoncé une application exclusive pour iPad , appelée Swift Playgrounds , destinée à apprendre aux gens à coder en Swift. L'application est présentée dans une interface de type jeu vidéo 3D qui fournit des commentaires lorsque les lignes de code sont placées dans un certain ordre et exécutées.

En janvier 2017, Chris Lattner a annoncé son départ d'Apple pour un nouveau poste chez Tesla Motors , le rôle de chef de projet Swift revenant au vétéran de l'équipe Ted Kremenek.

Lors de la WWDC 2019, Apple a annoncé SwiftUI avec Xcode 11, qui fournit un cadre pour la conception de structures d'interface utilisateur déclaratives sur toutes les plateformes Apple.

Les téléchargements officiels du SDK et de la chaîne d'outils pour la distribution Ubuntu de Linux sont disponibles depuis Swift 2.2, avec d'autres distributions ajoutées depuis Swift 5.2.4, CentOS et Amazon Linux. Il existe également un SDK non officiel et un package de chaîne d'outils natif pour Android.

Plateformes

Les plateformes prises en charge par Swift sont les systèmes d'exploitation d'Apple ( Darwin , iOS , iPadOS , macOS , tvOS , watchOS ), Linux , Windows et Android .

Un aspect clé de la conception de Swift est sa capacité à interagir avec l'énorme corpus de code Objective-C existant développé pour les produits Apple au cours des décennies précédentes, tels que les frameworks Cocoa et Cocoa Touch . Sur les plateformes Apple, il est lié à la bibliothèque d'exécution Objective-C , qui permet aux codes C , Objective-C , C++ et Swift de s'exécuter dans un seul programme.

Historique des versions

Caractéristiques

Swift est un langage de programmation à usage général qui utilise des concepts théoriques modernes de langage de programmation et s'efforce de présenter une syntaxe simple mais puissante. Swift intègre des innovations et des conventions de divers langages de programmation, avec une inspiration notable d'Objective-C, qu'il a remplacé comme langage de développement principal sur les plateformes Apple.

Swift a été conçu pour être sûr et convivial pour les nouveaux programmeurs sans sacrifier la vitesse. Par défaut, Swift gère automatiquement toute la mémoire et garantit que les variables sont toujours initialisées avant utilisation. Les accès aux tableaux sont vérifiés pour les erreurs hors limites et les opérations sur les entiers sont vérifiées pour les dépassements de capacité. Les noms de paramètres permettent de créer des API claires. Les protocoles définissent les interfaces que les types peuvent adopter, tandis que les extensions permettent aux développeurs d'ajouter plus de fonctions aux types existants. Swift permet la programmation orientée objet avec la prise en charge des classes , du sous-typage et du remplacement de méthode . Les options permettent de gérer les valeurs nil de manière explicite et sûre. Les programmes simultanés peuvent être écrits en utilisant la syntaxe async/await et les acteurs isolent l'état mutable partagé afin d'éliminer les courses de données.

Syntaxe de base

La syntaxe de Swift est similaire à celle des langages de type C. Le code commence à s'exécuter dans la portée globale par défaut. Alternativement, l' attribut peut être appliqué à une déclaration de structure, de classe ou d'énumération pour indiquer qu'il contient le point d'entrée du programme. @main

Le programme « Hello, World ! » de Swift est :

imprimer ( "Bonjour tout le monde !" )

La fonction utilisée ici est incluse dans la bibliothèque standard de Swift, qui est disponible pour tous les programmes sans avoir besoin d'importer des modules externes. Les instructions dans Swift ne doivent pas nécessairement se terminer par un point-virgule, mais des points-virgules sont nécessaires pour séparer plusieurs instructions écrites sur la même ligne. Les commentaires sur une seule ligne commencent par et continuent jusqu'à la fin de la ligne en cours. Les commentaires sur plusieurs lignes sont contenus par les caractères et . Les constantes sont déclarées avec le mot-clé et les variables avec le mot-clé. Les valeurs doivent être initialisées avant d'être lues. Les valeurs peuvent déduire leur type en fonction du type de la valeur initiale fournie. Si la valeur initiale est définie après la déclaration de la valeur, un type doit être déclaré explicitement. print(_:separator:terminator:)///**/letvar

laissez 
highScoreThreshold 
= 
1000 
// Une constante de type Int. Le type a été déduit en fonction de la valeur fournie.
var 
currentScore 
= 
980 
// Une variable de type Int.
currentScore 
= 
1200 
// La valeur des variables peut changer au fil du temps.
laissez 
playerMessage : 
String 
// Une constante avec un type explicite String.
si 
currentScore 
> 
highScoreThreshold 
{
playerMessage 
= 
"Vous êtes un joueur de haut niveau !"
} 
autre 
{
playerMessage 
= 
"Meilleure chance la prochaine fois."
}
print ( playerMessage ) 
// Imprime « Vous êtes un joueur de haut niveau ! »

Le flux de contrôle dans Swift est géré avec des instructions if-else , guard et switch , ainsi que des boucles while et for-in . Les instructions prennent un paramètre booléen et exécutent le corps de l' instruction si la condition est vraie, sinon, elles exécutent le corps facultatif. syntax fournit du sucre syntaxique pour vérifier l'existence d'une valeur facultative et la déballer en même temps.ififelseif-let

soit 
un nombre 
= 
42
si 
someNumber 
% 
2 
== 
0 
{ 
// Utilisez l'opérateur de reste pour trouver le reste de someNumber divisé par 2.
print ( " \( someNumber ) est pair." )
} 
autre 
{
print ( " \( someNumber ) est impair." )
}
// Imprime « 42 est pair ».

Les fonctions sont définies avec le funcmot clé. Les paramètres de fonction peuvent avoir des noms qui permettent aux appels de fonction de se lire comme des phrases. Un trait de soulignement avant le nom du paramètre permet d'omettre l'étiquette de l'argument du site d'appel. Les tuples peuvent être utilisés par les fonctions pour renvoyer plusieurs éléments de données à la fois.

func 
constructGreeting ( pour 
nom : 
String ) 
-> 
String 
{
retour 
"Bonjour \( nom ) !"
}
laissez 
greeting 
= 
constructGreeting ( pour : 
"Craig" )
imprimer ( salutation ) 
// Imprime "Bonjour Craig ! "

Les fonctions, et les fonctions anonymes appelées fermetures , peuvent être attribuées à des propriétés et transmises au programme comme n'importe quelle autre valeur.

fonction 
diviserParDeux ( _aNum 
: Int ) - > Int {
renvoie 
aNum 
/ 
2
}
func 
multiplierByTwo ( _ 
aNum : 
Int ) 
-> 
Int 
{
renvoie 
aNum 
* 
2
}
laissez 
mathOperation 
= 
multiplierParDeux
print ( mathOperation ( 21 )) 
// Imprime "42"

guardLes instructions exigent que la condition donnée soit vraie avant de continuer au-delà de l' guardinstruction, sinon le corps de la elseclause fournie est exécuté. La elseclause doit quitter le contrôle du bloc de code dans lequel l' guardinstruction apparaît. guardLes instructions sont utiles pour garantir que certaines exigences sont remplies avant de poursuivre l'exécution du programme. En particulier, elles peuvent être utilisées pour créer une version non encapsulée d'une valeur facultative qui est garantie comme étant non nulle pour le reste de la portée englobante.

func 
diviser ( numérateur : 
Int ?, 
byDenominator 
dénominateur : 
Int ) 
-> 
Int ? 
{
dénominateur 
de garde != 
0 
else 
{
print ( "Impossible de diviser par 0." )
retourner 
nul
}
garde 
let 
numérateur 
else 
{
print ( "Le numérateur fourni est nul." )
retourner 
nul
}
retourner 
le numérateur 
/ 
dénominateur
}
soit 
le résultat 
= 
diviser ( numérateur : 
3 , 
par dénominateur : 
0 )
print ( "Le résultat de la division est : \( résultat ) " )
// Imprime :
// "Impossible de diviser par 0."
// "Le résultat de la division est : nul."

switchLes instructions comparent une valeur à plusieurs valeurs potentielles, puis exécutent un bloc de code associé. switchLes instructions doivent être exhaustives, soit en incluant des cas pour toutes les valeurs possibles, soit en incluant un defaultcas qui est exécuté lorsque la valeur fournie ne correspond à aucun des autres cas. switchLes cas ne tombent pas implicitement, bien qu'ils puissent le faire explicitement avec le fallthroughmot-clé. La correspondance de motifs peut être utilisée de différentes manières dans switchles instructions. Voici un exemple d'un entier correspondant à un certain nombre de plages potentielles :

soit 
un nombre 
= 
42
changer 
un certain nombre 
{
cas 
..< 0 :
print ( " \( someNumber ) négatif." )
cas 
0 :
print ( " \( someNumber ) est 0. " )
cas 
1. .. 9 :
print ( " \( someNumber ) supérieur à 0, mais inférieur à 10. " )
défaut :
print ( " \( someNumber ) est supérieur à 9. " )
}
// Imprime « 42 est supérieur à 9 ».

for-inles boucles itèrent sur une séquence de valeurs :

laissez 
les noms 
= 
[ "Will" , 
"Anna" , 
"Bart" ]
pour 
le nom 
dans 
les noms 
{
imprimer ( nom )
}
// Imprime :
// Volonté
//Anne
// Bart

whileles boucles itèrent tant que la condition booléenne donnée est évaluée àtrue :

// Additionnez tous les nombres de 1 à 5.
var 
i 
= 
1
var 
résultat 
= 
0
tant que 
i 
<= 
5 
{ 
// La boucle exécute son corps tant que i est inférieur ou égal à 5. 
résultat 
+= 
i 
// Ajoute i au résultat actuel.
i 
+= 
1 
// Incrémenter i de 1.
}
imprimer ( résultat ) 
// Imprime "15"

Support de fermeture

Swift prend en charge les fermetures , qui sont des blocs de fonctionnalités autonomes qui peuvent être transmis et utilisés dans le code, et peuvent également être utilisés comme fonctions anonymes . Voici quelques exemples :

// Le type de fermeture, défini par ses valeurs d'entrée et de sortie, peut être spécifié en dehors de la fermeture :
laissez 
closure1 : 
( Int , 
Int ) 
-> 
Int 
= 
{ 
arg1 , 
arg2 
dans
retourner 
arg1 
+ 
arg2
}
// …ou à l’intérieur :
laissez 
closure2 
= 
{ 
( arg1 : 
Int , 
arg2 : 
Int ) 
-> 
Int 
dans
retourner 
arg1 
+ 
arg2
}
// Dans la plupart des cas, le type de retour de la fermeture peut être déduit automatiquement par le compilateur.
laissez 
closure3 
= 
{ 
arg1 : 
Int , 
arg2 : 
Int 
dans
retourner 
arg1 
+ 
arg2
}

Les fermetures peuvent être assignées à des variables et des constantes, et peuvent être transmises à d'autres fonctions ou fermetures en tant que paramètres. Les fermetures à expression unique peuvent supprimer le returnmot-clé.

Swift dispose également d'une syntaxe de fermeture de fin, qui permet d'écrire la fermeture après la fin de l'appel de fonction plutôt que dans la liste des paramètres de la fonction. Les parenthèses peuvent être complètement omises si la fermeture est le seul paramètre de la fonction :

// Cette fonction prend une fermeture qui ne reçoit aucun paramètre d'entrée et renvoie un entier,
// l'évalue et utilise la valeur de retour de la fermeture (un Int) comme valeur de retour de la fonction.
func 
foo ( fermeture 
bar : 
() 
-> 
Int ) 
-> 
Int 
{
barre de retour ()
}
// Sans syntaxe de fermeture de fin :
foo ( fermeture : 
{ 
retour 
1 
})
// Avec une syntaxe de fermeture de fin et un retour implicite :
foo 
{ 
1 
}

À partir de la version 5.3, Swift prend en charge plusieurs fermetures de fin :

// Cette fonction passe le retour de la première fermeture comme paramètre de la seconde, 
// et renvoie le résultat de la seconde fermeture : 
func 
foo ( bar : 
() 
-> 
Int , 
baz : 
( Int ) 
-> 
Int ) 
-> 
Int 
{ 
return 
baz ( bar ()) 
}
// Sans fermetures de fin : 
foo ( bar : 
{ 
return 
1 
}, 
baz : 
{ 
x 
in 
return 
x 
+ 
1 
})
// Avec 1 fermeture de fin : 
foo ( bar : 
{ 
return 
1 
}) 
{ 
x 
in 
return 
x 
+ 
1 
}
// Avec 2 fermetures de fin (seul le nom de l'argument de la première fermeture est omis) : 
foo 
{ 
return 
1 
} 
baz : 
{ 
x 
in 
return 
x 
+ 
1 
}

Swift fournira des noms d'arguments abrégés pour les fermetures en ligne, supprimant ainsi la nécessité de nommer explicitement tous les paramètres des fermetures. Les arguments peuvent être référencés avec les noms $0, $1, $2, etc. :

laissez 
les noms 
= 
[ "Joséphine" , 
"Steve" , 
"Chris" , 
"Barbara" ]
// le filtre appelle la fermeture donnée pour chaque valeur dans les noms. 
// Les valeurs avec un nombre de caractères inférieur à 6 sont conservées, les autres sont supprimées. 
let 
shortNames 
= 
names . filter 
{ 
$0 . count 
< 
6 
}
print ( shortNames ) 
// Imprime "["Steve", "Chris"]"

Les fermetures peuvent capturer des valeurs de leur portée environnante. La fermeture fera référence à cette valeur capturée tant que la fermeture existe :

func 
makeMultiplier ( withMultiple 
multiple : 
Int ) 
-> 
( Int ) 
-> 
( Int ) 
{ 
// Créer et renvoyer une fermeture qui prend un Int et renvoie l'entrée multipliée par la valeur de multiple. 
return 
{ 
$0 
* 
multiple 
} 
}
laissez 
multiplier 
= 
makeMultiplier ( withMultiple : 
3 ) 
print ( multiplier ( 3 )) 
// Imprime "9" 
print ( multiplier ( 10 )) 
// Imprime "30"

Prise en charge des chaînes

StringLa bibliothèque standard Swift inclut des types compatibles Unicode Character. Les valeurs de chaîne peuvent être initialisées avec un littéral de chaîne, une séquence de caractères entourée de guillemets doubles. Les chaînes peuvent être concaténées avec l' +opérateur :

var 
someString 
= 
"Bonjour", 
someString 
+= 
" world!"

L'interpolation de chaîne permet de créer une nouvelle chaîne à partir d'autres valeurs et expressions. Les valeurs écrites entre parenthèses précédées d'un a \seront insérées dans la chaîne littérale englobante :

var 
currentScore 
= 
980 
print ( "Votre score est \( currentScore ) . " )
// Imprime « Votre score est de 980 ».

Une boucle for-in peut être utilisée pour parcourir les caractères contenus dans une chaîne :

pour 
le caractère 
dans 
« Swift » 
{ 
print ( caractère )
 } 
// S 
// w 
// i 
// f 
// t

Lorsque le framework Foundation est importé, Swift relie de manière invisible le type String à NSString, la classe String couramment utilisée dans Objective-C.

Objets appelables

Dans Swift, les objets appelables sont définis à l'aide de callAsFunction.

struct 
CallableStruct 
{ 
var 
valeur : 
Int 
func 
callAsFunction ( _ 
nombre : 
Int , 
échelle : 
Int ) 
{ 
print ( échelle 
* 
( nombre 
+ 
valeur )) 
} 
} 
let 
callable 
= 
CallableStruct ( valeur : 
100 ) 
callable ( 4 , 
échelle : 
2 ) 
callable . callAsFunction ( 4 , 
échelle : 
2 ) 
// Les deux appels de fonction impriment 208.

Contrôle d'accès

Swift prend en charge cinq niveaux de contrôle d'accès pour les symboles : open, public, internal, fileprivateet private. Contrairement à de nombreux langages orientés objet, ces contrôles d'accès ignorent les hiérarchies d'héritage : privateindique qu'un symbole est accessible uniquement dans la portée immédiate , fileprivateindique qu'il est accessible uniquement à partir du fichier, internalindique qu'il est accessible dans le module conteneur, publicindique qu'il est accessible à partir de n'importe quel module et open(uniquement pour les classes et leurs méthodes) indique que la classe peut être sous-classée en dehors du module.

Options et enchaînement

Une fonctionnalité importante de Swift est l'option de type , qui permet aux références ou aux valeurs de fonctionner d'une manière similaire au modèle courant en C , où un pointeur peut soit faire référence à une valeur spécifique, soit à aucune valeur du tout. Cela implique que les types non optionnels ne peuvent pas entraîner d' erreur de pointeur nul ; le compilateur peut s'assurer que cela n'est pas possible.

Les types optionnels sont créés avec l' Optionalénumération. Pour créer un entier nullable, on utiliserait une déclaration similaire à var optionalInteger: Optional<Int>. Comme dans C#, Swift inclut également du sucre syntaxique pour cela, permettant d'indiquer qu'une variable est facultative en plaçant un point d'interrogation après le nom du type, var optionalInteger: Int?. Les variables ou constantes marquées facultatives ont soit une valeur du type sous-jacent, soit sont nil. Les types optionnels encapsulent le type de base, ce qui donne une instance différente. Stringet String?sont des types fondamentalement différents, le premier est de type Stringtandis que le second est un Optionalqui peut contenir une certaine Stringvaleur.

Pour accéder à la valeur à l'intérieur, en supposant qu'elle ne soit pas nulle, elle doit être déballée pour exposer l'instance à l'intérieur. Cela s'effectue avec l' !opérateur :

laissez 
myValue 
= 
anOptionalInstance !. someMethod ()

Dans ce cas, l' !opérateur se déballe anOptionalInstancepour exposer l'instance à l'intérieur, ce qui permet d'effectuer l'appel de méthode sur celle-ci. Si anOptionalInstanceest nul, une erreur de pointeur nul se produit, mettant fin au programme. C'est ce qu'on appelle le déballage forcé. Les options peuvent être déballées en toute sécurité à l'aide du chaînage optionnel qui teste d'abord si l'instance est nulle, puis la déballe si elle n'est pas nulle :

laissez 
maValeur 
= 
uneInstanceOptionnelle ?. uneMéthode ()

Dans ce cas, le runtime n'appelle someMethodque if anOptionalInstanceis not nil, supprimant l'erreur. A ?doit être placé après chaque propriété facultative. Si l'une de ces propriétés est nulle, l'expression entière est évaluée comme nulle. L'origine du terme chaînage vient du cas le plus courant où plusieurs appels/getters de méthode sont chaînés ensemble. Par exemple :

laissez 
un locataire 
= 
un bâtiment . tenantList [ 5 ] 
laissez 
leur bail 
= 
un locataire . leaseDetails 
laissez 
leaseStart 
= 
leur bail ?. startDate

peut être réduit à :

laissez 
leaseStart 
= 
aBuilding . tenantList [ 5 ]. leaseDetails ?. startDate

L'utilisation d'options par Swift permet au compilateur d'utiliser une répartition statique car l'action de déballage est appelée sur une instance définie (le wrapper), au lieu de se produire dans un système de répartition d'exécution.

Types de valeur

Dans de nombreux langages orientés objet, les objets sont représentés en interne en deux parties. L'objet est stocké sous forme de bloc de données placé sur le tas , tandis que le nom (ou « handle ») de cet objet est représenté par un pointeur . Les objets sont transmis entre les méthodes en copiant la valeur du pointeur, ce qui permet à toute personne disposant d'une copie d'accéder aux mêmes données sous-jacentes sur le tas. En revanche, les types de base comme les entiers et les valeurs à virgule flottante sont représentés directement ; le handle contient les données, pas un pointeur vers celles-ci, et ces données sont transmises directement aux méthodes par copie. Ces styles d'accès sont appelés passage par référence dans le cas des objets, et passage par valeur pour les types de base.

Les deux concepts ont leurs avantages et leurs inconvénients. Les objets sont utiles lorsque les données sont volumineuses, comme la description d'une fenêtre ou le contenu d'un document. Dans ces cas, l'accès à ces données est assuré par la copie d'une valeur 32 ou 64 bits, plutôt que par la copie d'une structure de données entière. Cependant, les valeurs plus petites comme les entiers ont la même taille que les pointeurs (généralement les deux sont constitués d'un seul mot ), il n'y a donc aucun avantage à transmettre un pointeur plutôt que la valeur.

Swift offre un support intégré pour les objets utilisant soit la sémantique de passage par référence, soit la sémantique de passage par valeur, la première utilisant la classdéclaration et la seconde utilisant struct. Les structures dans Swift ont presque toutes les mêmes fonctionnalités que les classes : méthodes, implémentation de protocoles et utilisation des mécanismes d'extension. Pour cette raison, Apple qualifie toutes les données de manière générique d' instances , par opposition à des objets ou des valeurs. Les structures ne prennent cependant pas en charge l'héritage.

Le programmeur est libre de choisir la sémantique la plus appropriée pour chaque structure de données de l'application. Les structures plus grandes comme les fenêtres seraient définies comme des classes, ce qui leur permettrait d'être transmises sous forme de pointeurs. Les structures plus petites, comme un point 2D, peuvent être définies comme des structures, qui seront transmises par valeur et permettront un accès direct à leurs données internes sans indirection ni comptage de références. L'amélioration des performances inhérente au concept de transmission par valeur est telle que Swift utilise ces types pour presque tous les types de données courants, y compris Intet Double, et les types normalement représentés par des objets, comme Stringet Array. L'utilisation de types de valeur peut également entraîner des améliorations significatives des performances dans les applications utilisateur.

Array, Dictionary, et Settous utilisent la copie à l'écriture afin que leurs données ne soient copiées que si et quand le programme tente de modifier une valeur dans celles-ci. Cela signifie que les différents accesseurs ont en fait un pointeur vers le même stockage de données. Ainsi, alors que les données sont physiquement stockées comme une instance en mémoire, au niveau de l'application, ces valeurs sont séparées et la séparation physique est appliquée par copie à l'écriture uniquement si nécessaire.

Extensions

Les extensions ajoutent de nouvelles fonctionnalités à un type existant, sans qu'il soit nécessaire de sous-classer ou même d'avoir accès au code source d'origine. Les extensions peuvent ajouter de nouvelles méthodes, des initialiseurs, des propriétés calculées, des indices et des conformités de protocole. Un exemple pourrait être d'ajouter un correcteur orthographique au Stringtype de base, ce qui signifie que toutes les instances de Stringdans le programme obtiennent la possibilité de vérifier l'orthographe. Le système est également largement utilisé comme technique d'organisation, permettant de rassembler du code associé dans des extensions de type bibliothèque.

Les extensions sont déclarées avec le extensionmot-clé.

structure 
Rectangle 
{
laisser 
largeur : 
Double
hauteur de let : 
Double
}
extension 
Rectangle 
{
var 
zone : 
Double 
{
hauteur 
de retour * 
largeur
}
}

Programmation orientée protocole

Les protocoles garantissent qu'un type particulier implémente un ensemble de méthodes ou de propriétés, ce qui signifie que d'autres instances du système peuvent appeler ces méthodes sur n'importe quelle instance implémentant ce protocole. Cette méthode est souvent utilisée dans les langages orientés objet modernes comme substitut à l'héritage multiple , bien que les ensembles de fonctionnalités ne soient pas entièrement similaires.

En Objective-C et dans la plupart des autres langages implémentant le concept de protocole, il appartient au programmeur de s'assurer que les méthodes requises sont implémentées dans chaque classe. Swift ajoute la possibilité d'ajouter ces méthodes à l'aide d'extensions et d'utiliser la programmation générique (génériques) pour les implémenter. Ensemble, ces éléments permettent d'écrire des protocoles une fois et de prendre en charge une grande variété d'instances. De plus, le mécanisme d'extension peut être utilisé pour ajouter la conformité du protocole à un objet qui ne répertorie pas ce protocole dans sa définition.

Par exemple, un protocole peut être déclaré appelé Printable, ce qui garantit que les instances conformes au protocole implémentent une descriptionpropriété et une printDetails()exigence de méthode :

// Définir un protocole nommé Printable 
protocol 
Printable 
{ 
var 
description : 
String 
{ 
get 
} 
// Une exigence de propriété en lecture seule 
func 
printDetails () 
// Une exigence de méthode 
}

Ce protocole peut désormais être adopté par d’autres types :

// Adopter le protocole Printable dans une 
classe class 
MyClass : 
Printable 
{ 
var 
description : 
String 
{ 
return 
"Une instance de MyClass" 
}
fonction 
printDetails () 
{ 
print ( description ) 
} 
}

Les extensions peuvent être utilisées pour ajouter la conformité au protocole aux types. Les protocoles eux-mêmes peuvent également être étendus pour fournir des implémentations par défaut de leurs exigences. Les adoptants peuvent définir leurs propres implémentations ou utiliser l'implémentation par défaut :

extension 
Printable 
{ 
// Toutes les instances Printable recevront cette implémentation, ou elles peuvent définir la leur. 
func 
printDetails () 
{ 
print ( description ) 
} 
}
// Bool est désormais conforme à Printable et hérite de l'implémentation printDetails() ci-dessus. 
extension 
Bool : 
Printable 
{ 
var 
description : 
String 
{ 
return 
"Une instance de Bool avec la valeur : \( self ) " 
}
}

En Swift, comme dans de nombreux langages modernes prenant en charge les interfaces, les protocoles peuvent être utilisés comme types, ce qui signifie que les variables et les méthodes peuvent être définies par protocole au lieu de leur type spécifique :

func 
getSomethingPrintable () 
-> 
tout 
Imprimable 
{ 
return 
true 
}
var 
someSortOfPrintableInstance 
= 
getSomethingPrintable ( 
) print ( someSortOfPrintableInstance.description )
// Imprime « Une instance de Bool avec la valeur : true »

Peu importe le type concret de someSortOfPrintableInstance, le compilateur s'assurera qu'il est conforme au protocole et donc que ce code est sûr. Cette syntaxe signifie également que les collections peuvent également être basées sur des protocoles, comme let printableArray = [any Printable].

Les extensions et les protocoles sont largement utilisés dans la bibliothèque standard de Swift ; dans Swift 5.9, environ 1,2 % de tous les symboles de la bibliothèque standard étaient des protocoles, et 12,3 % étaient des exigences de protocole ou des implémentations par défaut. Par exemple, Swift utilise des extensions pour ajouter le Equatableprotocole à plusieurs de ses types de base, comme les chaînes et les tableaux, ce qui leur permet d'être comparés à l' ==opérateur. Le Equatableprotocole définit également cette implémentation par défaut :

func 
!=< T 
: 
Équivalent >( lhs : 
T , 
rhs : 
T ) 
-> 
Bool

Cette fonction définit une méthode qui fonctionne sur toute instance conforme à Equatable, en fournissant un opérateur différent de . Toute instance, classe ou structure, obtient automatiquement cette implémentation simplement en se conformant à Equatable.

Les protocoles, les extensions et les génériques peuvent être combinés pour créer des API sophistiquées. Par exemple, les contraintes permettent aux types d'adopter conditionnellement des protocoles ou des méthodes en fonction des caractéristiques du type adoptant. Un cas d'utilisation courant peut être l'ajout d'une méthode sur les types de collection uniquement lorsque les éléments contenus dans la collection sont Equatable:

extension 
Tableau 

Élément : 
Équivalent 
{
// allEqual ne sera disponible que sur les instances de Array qui contiennent des éléments Equatable. 
func 
allEqual () 
-> 
Bool 
{ 
for 
element 
in 
self 
{ 
if 
element 
!= 
self . first 
{ 
return 
false 
} 
} 
return 
true 
} 
}

Concurrence

Swift 5.5 a introduit la concurrence structurée dans le langage. La concurrence structurée utilise une syntaxe Async/await similaire à Kotlin, JavaScript et Rust. Une fonction asynchrone est définie avec le asyncmot-clé après la liste de paramètres. Lors de l'appel d'une fonction asynchrone, le awaitmot-clé doit être écrit avant la fonction pour indiquer que l'exécution sera potentiellement suspendue pendant l'appel de la fonction. Lorsqu'une fonction est suspendue, le programme peut exécuter une autre fonction concurrente dans le même programme. Cette syntaxe permet aux programmes d'appeler clairement les points de suspension potentiels et d'éviter une version de la pyramide de la mort (programmation) causée par l'utilisation auparavant répandue des rappels de fermeture.

func 
downloadText ( nom : 
String ) 
async 
-> 
String 
{ 
let 
result 
= 
// ... un code de téléchargement asynchrone ... 
return 
result 
}
laissez 
le texte 
= 
attendre 
le téléchargement du texte ( "texte1" )

La async letsyntaxe permet à plusieurs fonctions de s'exécuter en parallèle. awaitest à nouveau utilisé pour marquer le point auquel le programme s'arrêtera pour attendre la fin des asyncfonctions appelées précédemment.

// Chacun de ces appels à downloadText s'exécutera en parallèle. 
async 
let 
text1 
= 
downloadText ( name : 
"text1" ) 
async 
let 
text2 
= 
downloadText ( name : 
"text2" ) 
async 
let 
text3 
= 
downloadText ( name : 
"text3" )
laissez 
textToPrint 
= 
wait 
[ text1 , 
text2 , 
text3 ] 
// Suspend jusqu'à ce que les trois appels downloadText soient retournés. 
print ( textToPrint )

Les tâches et les groupes de tâches peuvent être créés explicitement pour créer un nombre dynamique de tâches enfants pendant l'exécution :

laissez 
taskHandle 
= 
Tâche 
{ 
wait 
downloadText ( nom : 
"someText" ) 
}
laissez 
le résultat 
= 
attendre 
taskHandle . valeur

Swift utilise le modèle Actor pour isoler l'état mutable, permettant à différentes tâches de muter l'état partagé de manière sécurisée. Les acteurs sont déclarés avec le actormot-clé et sont des types de référence, comme les classes. Une seule tâche peut accéder à l'état mutable d'un acteur en même temps. Les acteurs peuvent accéder et muter librement leur propre état interne, mais le code exécuté dans des tâches distinctes doit marquer chaque accès avec le awaitmot-clé pour indiquer que le code peut s'interrompre jusqu'à ce que d'autres tâches aient fini d'accéder à l'état de l'acteur.

acteur 
Répertoire 
{ 
var 
noms : 
[ String ] 
= 
[]
func 
add ( nom : 
chaîne ) 
{ 
noms . append ( nom ) 
} 
}
laissez 
répertoire 
= 
Répertoire ()
// Le code est suspendu jusqu'à ce que d'autres tâches aient fini d'accéder à l'acteur. 
wait 
directory . add ( name : 
"Tucker" ) 
print ( wait 
directory . names )

Bibliothèques, exécution, développement

Sur les systèmes Apple, Swift utilise le même runtime que le système Objective-C existant , mais nécessite iOS 7 ou macOS 10.9 ou supérieur. Il dépend également de Grand Central Dispatch . Le code Swift et Objective-C peut être utilisé dans un seul programme, et par extension, C et C++ également. À partir de Swift 5.9, le code C++ peut être utilisé directement à partir du code Swift. Dans le cas d'Objective-C, Swift a un accès considérable au modèle objet et peut être utilisé pour sous-classer, étendre et utiliser le code Objective-C pour fournir un support de protocole. L'inverse n'est pas vrai : une classe Swift ne peut pas être sous-classée en Objective-C.

Pour faciliter le développement de tels programmes et la réutilisation du code existant, Xcode 6 et les versions ultérieures proposent un système semi-automatisé qui construit et maintient un en-tête de pont pour exposer le code Objective-C à Swift. Cela prend la forme d'un fichier d'en-tête supplémentaire qui définit ou importe simplement tous les symboles Objective-C nécessaires au code Swift du projet. À ce stade, Swift peut faire référence aux types, fonctions et variables déclarés dans ces importations comme s'ils étaient écrits en Swift. Le code Objective-C peut également utiliser directement le code Swift, en important un fichier d'en-tête maintenu automatiquement avec les déclarations Objective-C des symboles Swift du projet. Par exemple, un fichier Objective-C dans un projet mixte appelé « MyApp » pourrait accéder aux classes ou fonctions Swift avec le code #import "MyApp-Swift.h". Cependant, tous les symboles ne sont pas disponibles via ce mécanisme : l'utilisation de fonctionnalités spécifiques à Swift comme les types génériques, les types facultatifs non-objet, les énumérations sophistiquées ou même les identifiants Unicode peut rendre un symbole inaccessible depuis Objective-C.

Swift offre également un support limité pour les attributs , des métadonnées lues par l'environnement de développement et qui ne font pas nécessairement partie du code compilé. Comme Objective-C, les attributs utilisent la @syntaxe, mais l'ensemble actuellement disponible est restreint. Un exemple est l' @IBOutletattribut, qui marque une valeur donnée dans le code comme un outlet , disponible pour une utilisation dans Interface Builder (IB). Un outlet est un périphérique qui lie la valeur de l'affichage à l'écran à un objet dans le code.

Sur les systèmes non Apple, Swift ne dépend pas d'un runtime Objective-C ou d'autres bibliothèques système Apple ; un ensemble d'implémentations Swift « Corelib » les remplace. Il s'agit notamment d'un « swift-corelibs-foundation » pour remplacer le Foundation Kit , d'un « swift-corelibs-libdispatch » pour remplacer le Grand Central Dispatch et d'un « swift-corelibs-xctest » pour remplacer les API XCTest de Xcode .

Depuis 2019, avec Xcode 11, Apple a également ajouté un nouveau paradigme d'interface utilisateur majeur appelé SwiftUI. SwiftUI remplace l'ancien paradigme Interface Builder par un nouveau paradigme de développement déclaratif.

Gestion de la mémoire

Swift utilise le comptage automatique des références (ARC) pour gérer la mémoire . Chaque instance d'une classe ou d'une fermeture conserve un décompte de références qui permet de comptabiliser le nombre de références conservées par le programme. Lorsque ce décompte atteint 0, l'instance est désallouée. Cette désallocation automatique élimine le besoin d'un récupérateur de mémoire, car les instances sont désallouées dès qu'elles ne sont plus nécessaires.

Un cycle de référence fort peut se produire si deux instances se référencent fortement l'une l'autre (par exemple, A référence B, B référence A). Étant donné qu'aucun des deux nombres de références d'instances ne peut atteindre zéro, aucun n'est jamais désalloué, ce qui entraîne une fuite de mémoire . Swift fournit les mots-clés weaket unownedpour empêcher les cycles de référence forts. Ces mots-clés permettent de référencer une instance sans incrémenter son nombre de références. weakLes références doivent être des variables facultatives, car elles peuvent changer et devenir nil. Toute tentative d'accès à une unownedvaleur qui a déjà été désallouée entraîne une erreur d'exécution.

Une fermeture au sein d'une classe peut également créer un cycle de référence fort en capturant des auto-références. Les auto-références à traiter comme faibles ou sans propriétaire peuvent être indiquées à l'aide d'une liste de capture.

classe 
Personne 
{
laissez 
le nom : 
chaîne
weak 
var 
home : 
Home ? 
// Défini comme une référence faible afin de briser le cycle de référence. Les références faibles n'incrémentent pas le nombre de références de l'instance à laquelle elles font référence.
init ( nom : 
chaîne ) 
{
soi . nom 
= 
nom
}
deinit 
{ 
print ( "Désinitialisé \( nom ) " ) 
}
}
classe 
Accueil 
{
laissez 
l'adresse : 
chaîne
var 
propriétaire : 
Personne ?
init ( adresse : 
chaîne , 
propriétaire : 
personne ?) 
{
soi . adresse 
= 
adresse
soi-même . propriétaire 
= 
propriétaire
}
deinit 
{ 
print ( " Adresse \( désinitialisée ) " ) }
}
var 
stacy : 
Personne ? 
= 
Personne ( nom : 
"Stacy" )
var 
house21b : 
Maison ? 
= 
Maison ( adresse : 
"21b Baker Street" , 
propriétaire : 
stacy )
stacy ?. home 
= 
house21b 
// stacy et house42b se réfèrent désormais l'un à l'autre.
stacy 
= 
nil 
// Le nombre de références pour stacy est maintenant de 1, car house21b détient toujours une référence à celui-ci.
house21b 
= 
nil 
// le nombre de références de house21b tombe à 0, ce qui à son tour réduit le nombre de stacy à 0 car house21b était la dernière instance détenant une référence forte à stacy.
// Imprime :
// Désinitialisé 21b Baker Street
// Stacy désinitialisée

Débogage

Un élément clé du système Swift est sa capacité à être débogué et exécuté proprement dans l'environnement de développement, à l'aide d'une boucle de lecture-évaluation-impression (REPL), ce qui lui confère des propriétés interactives plus proches des capacités de script de Python que des langages de programmation système traditionnels . Le REPL est encore amélioré avec des aires de jeux , des vues interactives exécutées dans l'environnement Xcode ou l'application Playgrounds qui répondent aux modifications de code ou de débogueur à la volée. Les aires de jeux permettent aux programmeurs d'ajouter du code Swift ainsi que de la documentation Markdown. Les programmeurs peuvent parcourir le code et ajouter des points d'arrêt à l'aide de LLDB, soit dans une console, soit dans un IDE comme Xcode.

Comparaisons avec d'autres langues

Swift est considéré comme un langage de programmation de la famille C et est similaire à C de plusieurs manières :

  • La plupart des opérateurs en C apparaissent également en Swift, bien que certains opérateurs tels que +aient un comportement légèrement différent. Par exemple, en Swift, +piège en cas de débordement, tandis que &+est utilisé pour désigner le comportement de type C de l'encapsulation en cas de débordement.
  • Les accolades sont utilisées pour regrouper des instructions.
  • Les variables sont affectées à l'aide d'un signe égal , mais comparées à l'aide de deux signes égaux consécutifs . Un nouvel opérateur d'identité, ===, est fourni pour vérifier si deux éléments de données font référence au même objet .
  • Les instructions de contrôle while, if, et switchsont similaires, mais ont des fonctions étendues, par exemple, a switchqui prend des cas non entiers whileet ifprend en charge la correspondance de modèles et le déballage conditionnel des options, forutilise la syntaxe.for i in 1...10
  • Les crochets sont utilisés avec les tableaux , à la fois pour les déclarer et pour obtenir une valeur à un index donné dans l'un d'eux.

Il présente également des similitudes avec Objective-C :

  • Types numériques de base :Int, UInt, Float, Double
  • Les méthodes de classe sont héritées, comme les méthodes d'instance ; selfdans les méthodes de classe, il s'agit de la classe sur laquelle la méthode a été appelée.
  • forSyntaxe d' énumération similaire in.

Les différences avec Objective-C incluent :

  • Les instructions ne doivent pas nécessairement se terminer par des points-virgules ( ;), bien que ceux-ci doivent être utilisés pour autoriser plusieurs instructions sur une ligne.
  • Aucun fichier d'en-tête.
  • Utilise l'inférence de type .
  • Programmation générique .
  • Les fonctions sont des objets de première classe .
  • Les cas d'énumération peuvent avoir des données associées ( types de données algébriques ).
  • Les opérateurs peuvent être redéfinis pour les classes ( surcharge d'opérateur ) et de nouveaux opérateurs peuvent être définis.
  • Les chaînes prennent entièrement en charge Unicode . La plupart des caractères Unicode peuvent être utilisés dans les identifiants ou les opérateurs.
  • Aucune gestion des exceptions . Swift 2 introduit un modèle de gestion des erreurs différent et incompatible.
  • Plusieurs fonctionnalités des langages antérieurs de la famille C qui sont faciles à utiliser à mauvais escient ont été supprimées :
    • Les pointeurs ne sont pas exposés par défaut. Le programmeur n'a pas besoin de suivre et de marquer les noms pour le référencement ou le déréférencement.
    • Les affectations ne renvoient aucune valeur. Cela évite l'erreur courante consistant à écrire i = 0à la place de i == 0(ce qui génère une erreur de compilation).
    • Il n'est pas nécessaire d'utiliser breakdes instructions en switchblocs. Les cas individuels ne passent pas au cas suivant à moins que l' fallthroughinstruction ne soit utilisée.
    • Les variables et les constantes sont toujours initialisées et les limites du tableau sont toujours vérifiées.
    • Les dépassements d' entiers , qui entraînent un comportement indéfini pour les entiers signés en C, sont détectés comme une erreur d'exécution dans Swift. Les programmeurs peuvent choisir d'autoriser les dépassements en utilisant les opérateurs arithmétiques spéciaux &+, &-, et . Les propriétés et sont définies dans Swift pour tous les types d'entiers et peuvent être utilisées pour vérifier en toute sécurité les dépassements potentiels, au lieu de s'appuyer sur des constantes définies pour chaque type dans des bibliothèques externes.&*&/&%minmax
    • La forme à une seule instruction de ifand while, qui permet l'omission des accolades autour de l'instruction, n'est pas prise en charge.
    • L'énumération de style C for (int i = 0; i < c; i++), qui est sujette à des erreurs d'un octet , n'est pas prise en charge (à partir de Swift 3).
    • Les opérateurs d'incrémentation et de décrémentation pré et post ( i++, --i...) ne sont pas pris en charge (à partir de Swift 3), d'autant plus que forles instructions de style C ne sont pas non plus prises en charge à partir de Swift 3.

Développement et autres implémentations

Étant donné que Swift peut fonctionner sous Linux, il est parfois également utilisé comme langage côté serveur. Certains frameworks Web ont déjà été développés, tels que Kitura d' IBM (désormais abandonné), Perfect et Vapor .

Un groupe de travail officiel « API serveur » a également été lancé par Apple, dans lequel les membres de la communauté des développeurs Swift jouent un rôle central.

Une deuxième implémentation gratuite de Swift qui cible Cocoa , l'infrastructure de langage commun de Microsoft ( .NET Framework , maintenant .NET ) et la plate-forme Java et Android existe dans le cadre du compilateur Elements de RemObjects Software .

Des sous-ensembles de Swift ont été portés sur des plateformes supplémentaires, telles qu'Arduino et Mac OS 9. [

Plus d articles de Worldlex Wiki

Revenez a l index pour explorer davantage de pages sur l histoire, la science, la culture, la geographie et la societe en francais.

Explorer l index