Comme tout bon tuto, on va essayer d'y voir un peu plus clair sur ce beau framework, voir un peu les possibilités mais encore mettre en avant des exemples qui pourront vous intéresser dans vos applications.
Juste avant on va s'assurer que tout le monde a bien Xcode d'installé sur son mac pour éviter d'éventuels problèmes par la suite.
Installer XCode
La première étape est de se rendre sur l'App Store depuis votre mac, vous avez également la possibilité de télécharger plusieurs versions de Xcode depuis ce site fiable si vous avez besoin d'une version spécifique :

Normalement le téléchargement est un peu long et c'est normal. Une fois téléchargé vous n'avez plus qu'à le lancer depuis le Launchpad, ça vous proposera d'accepter des licences Apple (les trucs qu'on ne lit jamais) et de télécharger des composants additionnels comme le kit de développement iOS / macOS / tvOS / watchOS etc... le mieux est de les prendre tous si vous voulez tester le développement sur plusieurs types d'applications.
Configurer le simulateur iOS :
Xcode permet de tester vos apps sur des simulateurs, ça évite d'utiliser votre téléphone perso pour tester les apps.
Pour le configurer :
- Depuis XCode > Window > Devices and Simulators > Simulators
- Dans la barre latérale, cliquez sur l'icône + et sélectionner un iPhone de votre choix.

Hello, world :
Maintenant que tout le monde a son petit atelier prêt à fonctionner, nous allons créer notre premier projet afin de s'amuser avec Swift et SwiftUI.
Quand vous ouvrez XCode :
- Depuis XCode, cliquer sur Create a new XCode Project
- Sélectionner App sous la section iOS
- Nommer le projet (ex HelloWorldApprendreSwift)
- Dans Interface, choisir SwiftUI
- Dans language, choisir Swift
- Sélectionner Next, puis Create

Tadaaaaa 🎉 Xcode devrait ouvrir une nouvelle interface avec un fichier ContentView.swift avec du code SwiftUI prêt à fonctionner :

Lancer l'application :

Ok ok maintenant on a toutes les bases pour pouvoir continuer notre apprentissage, l'idée désormais va être de vous introduire à des concepts clés de SwiftUI :
- Texte et Modificateurs de Texte
- La structure d'une Vue SwiftUI
- Les HStack, VStack et ZStack
- Images et Gestion des ressources
- Boutons et interactions de base
- Espacements, Paddings et Alignements
- Ajouter du style à notre application
Texte et modificateurs de texte :
Le texte est l'un des éléments fondamentaux d'une interface utilisateur, il permet à l'utilisateur d'être dirigé améliorant l'expérience utilisateur.
En SwiftUI vous retrouverez le composant Text, il permet d'afficher du contenu textuel de façon simple et flexible.
Text("Bienvenue dans SwiftUI")

Vous pouvez également modifier la taille ainsi que la police :
Text("Titre principal")
.font(.largeTitle)
Text("Sous-titre")
.font(.title2)
Autres styles disponibles :
.largeTitle
.title
,.title2
,.title3
.headline
,.subheadline
.body
,.callout
,.caption
,.footnote

Appliquer des styles (gras, italique, souligné) :
Text("Texte en gras").bold()
Text("Texte en italique").italic()
Text("Texte souligné").underline()

Pour changer la couleur de votre texte vous pouvez ajouter .foregroundColor(.red)

On peut également ajouter un espacement entre le texte :
Text("Texte centré sur plusieurs lignes. Il s'adapte automatiquement.")
.multilineTextAlignment(.center)

D'autres alignements que vous pouvez retrouver :
- .leading (gauche)
- .center (centré)
- .trailing (droite)
Les modificateurs sont nombreux, vous pouvez également ajouter un fond et un contour au texte :
Text("Texte avec fond")
.padding()
.background(Color.yellow)
.cornerRadius(10)
Petite explication : Le .padding()
ajoute de l'espace autour du texte, le .background(Color.yellow)
ajoute un fond jaune à notre texte (on pourrait également utiliser .yellow) et le .cornerRadius(10)
arrondit les coins.
Afficher du texte dynamique :
SwiftUI permet d'afficher des textes de façon dynamique avec @State :
struct ContentView: View {
@State private var message = "Bienvenue"
var body: some View {
VStack {
Text(message)
.font(.title)
Button("Changer le texte") {
message = "Texte mis à jour !"
}
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
}
Le @State est ce qu'on appelle un property wrapper, on pourra le détailler avec d'autres properties par la suite. Concrètement @State gère un état mutable à l'intérieur d'une vue ce qui permet de déclencher automatiquement le rafraîchissement de cette vue lorsque la valeur de notre @State change, dans notre exemple, c'est la propriété message qui change de valeur.

Maintenant vous êtes un boss avec Text, en plus on a vu un peu comment personnaliser notre contenu ce qui peut vous donner des idées pour vos prochaines apps :)
La structure d'une vue SwiftUI
En SwiftUI, toutes les interfaces utilisateur sont définies à l'aide de ce qu'on appelle une Vue (de l'anglais View). Comprendre la structure d'une Vue c'est s'assurer de créer des applications modulaires et bien organisées, comme on aime.
Une vue c'est une déclaration de ce qui doit être affiché à l'écran. À la différence de UIKit, où on vient manipuler des éléments avec des références (UILabel, UIButton, etc...), SwiftUI décrit l'interface sous forme de code déclaratif.
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Bonjour, SwiftUI!")
.font(.largeTitle)
.padding()
}
}
#Preview {
ContentView()
}
Décomposition du code :
struct ContentView: View
définit une vue SwiftUI appelée ContentViewvar body: some View
contient l'interface de la vueText("Bonjour, SwiftUI!")
affiche un texte à l'écran.font(.largeTitle).padding()
applique des styles sur le texte qu'on affiche

Pour organiser une vue, on peut l'organiser avec plusieurs sous-vues, pour cela on utilise des stacks (VStack, HStack, ZStack). On pourra voir des exemples détaillés dans la suite de ce tuto.
struct ContentView: View {
var body: some View {
VStack {
Text("Titre")
.font(.title)
Text("Sous-titre")
.font(.subheadline)
.foregroundColor(.gray)
Button("Appuyez-moi") {
print("Bouton pressé")
}
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
.padding()
}
}
Avec VStack on a un empilement vertical d'un titre, d'un sous-titre et d'un bouton interactif.

Dès qu'une donnée change, SwiftUI reconstruit automatiquement la vue, c'est ce qu'on appelle la réactivité ; on a pu le voir tout à l'heure avec l'élément @State.
struct ContentView: View {
@State private var compteur = 0
var body: some View {
VStack {
Text("Compteur : \(compteur)")
.font(.title)
Button("Incrémenter") {
compteur += 1
}
.padding()
.background(Color.green)
.foregroundColor(.white)
.cornerRadius(10)
}
}
}

Une bonne pratique en SwiftUI est de venir découper les vues en plusieurs composants modulaires pour éviter les fichiers trop longs, ça permet notamment :
- une meilleure lisibilité du code
- une meilleure maintenabilité (dans le temps si un autre dev reprend le relais de l'app)
- etc..
HStack, VStack et ZStack, l'organisation par des mots
Comme nous avons pu le voir dans l'exemple précédent, la structure d'une page nécessite souvent l'utilisation de VStack, HStack... mais qui sont-ils, à quoi servent-ils ?
Ce sont ce qu'on appelle des conteneurs qui permettent de disposer des vues les unes par rapport aux autres, de façon horizontale (HStack), verticale (VStack) ou encore en superposition (ZStack).
VStack - Empilement vertical :
VStack {
Text("Premier")
Text("Deuxième")
Text("Troisième")
}

HStack - Disposition horizontale
HStack {
Text("🔵")
Text("🔴")
Text("🟢")
}

ZStack - Superposition des vues
ZStack {
Color.blue
Text("Texte au-dessus")
.font(.title)
.foregroundColor(.white)
}
.frame(width: 200, height: 100)

On peut également combiner des stacks afin de créer une interface plus élaborée.
VStack {
Text("Profil")
.font(.title)
HStack {
Image(systemName: "person.circle.fill")
.resizable()
.frame(width: 60, height: 60)
.foregroundColor(.blue)
VStack(alignment: .leading) {
Text("Nom : Giovanni Outerleys")
Text("Âge : 24")
}
}
}
.padding()

Dans l'exemple précédent on combine plusieurs stacks.

Plusieurs modificateurs sont eux aussi disponibles sur les stacks, comme .spacing
et .alignment
.
VStack(alignment: .leading, spacing: 16) {
Text("Titre")
.font(.title)
Text("Sous-titre")
Text("Description longue sur plusieurs lignes...")
}

Grâce à ça vous pouvez avoir un alignement du contenu et l'ajout d'un espace vertical entre les éléments.
Les stacks sont indispensables dans votre app afin de construire des interfaces claires et responsives, désormais vous avez tous les outils pour structurer une interface digne de ce nom !
Images et gestion des ressources
Pour pimper votre application rien de mieux que de belles images, elles jouent un rôle essentiel dans l'interface utilisateur pour éviter le vide intersidéral que laisse le fond blanc par défaut de votre app. Et devinez quoi ? SwiftUI propose une API simple et puissante pour gérer les images !
Afficher une image locale
Dans un premier temps vous devez déposer votre image dans les assets, c'est un dossier qui est dans toutes les applications.
Dans notre cas on va venir ouvrir le panneau Assets.xcassets puis déposer notre image chaton.jpg. Ensuite, on va ajouter dans notre vue un bout de code :
Image("chaton")


Redimensionner et styliser une image :
Dans SwiftUI vous avez pleins de modificateurs comme vous avez pu le voir précédemment, et le composant Image n'en manque pas !
Vous pouvez changer la taille avec .resizable()
et .frame()
:
Image("chaton")
.resizable()
.frame(width: 100, height: 100)
Garder le ratio avec .aspectRatio()
:
Image("chaton")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 150)
Le .fit
adapte l'image au cadre sans la déformer, et le .fill
la remplit en recadrant si besoin.

Vous pouvez également jouer avec le style visuel sur votre image :
Image("chaton")
.resizable()
.scaledToFit()
.frame(width: 150)
.clipShape(Circle())
.overlay(Circle().stroke(Color.white, lineWidth: 4))
.shadow(radius: 10)

Utiliser les SF Symbols

Apple fournit une bibliothèque d'icônes vectorielles appelées SF Symbols, intégrée dans SwiftUI. Ça évite d'utiliser d'autres solutions comme flaticon.
Image(systemName: "star.fill")
.font(.system(size: 40))
.foregroundColor(.yellow)

Il existe des centaines d'icônes disponibles juste ici : https://developer.apple.com/sf-symbols/
AsyncImage - Afficher une image distante
Disponible depuis iOS 15, SwiftUI propose le composant AsyncImage pour charger des images depuis une URL.
AsyncImage(url: URL(string: "https://picsum.photos/200")) { image in
image
.resizable()
.scaledToFit()
.frame(width: 150)
} placeholder: {
ProgressView()
}

Dans notre exemple, l'image est chargée depuis une URL distante, un loader s'affiche pendant le téléchargement (ProgressView).
Boutons et interactions de base
Les interactions sont au cœur d'une application, quand vous voulez que votre utilisateur valide son panier vous passez par un bouton, quand il se connecte aussi...
Créer un bouton simple
Button("Appuyez-moi") {
print("Le bouton a été pressé !")
}

Le premier paramètre est notre label (le texte affiché), le second est une closure qui définit l'action à exécuter.
Interaction avec @State
Bon c'est un peu de la triche on l'a déjà vu, mais vous pouvez évidemment modifier des données grâce à un bouton en utilisant @State.
struct ContentView: View {
@State private var compteur = 0
var body: some View {
VStack {
Text("Compteur : \(compteur)")
.font(.title)
Button("Incrémenter") {
compteur += 1
}
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
}

Quelques modificateurs disponibles pour les boutons
Button("Valider") {
print("Validation")
}
.padding()
.background(Color.green)
.foregroundColor(.white)
.font(.headline)
.cornerRadius(8)

Bouton 🤝 SF Symbols
Button(action: {
print("Favori ajouté")
}) {
Label("Ajouter", systemImage: "star.fill")
}
.padding()
.background(Color.yellow)
.foregroundColor(.black)
.cornerRadius(10)

On peut aussi désactiver un bouton avec .disabled(etat) :
Button("Confirmer") {
print("Confirmation")
}
.disabled(true)

Animation quand on clic
@State private var rotation = 0.0
Button("Tourner") {
withAnimation {
rotation += 45
}
}
.rotationEffect(.degrees(rotation))

Espacements, Paddings et Alignements
Afin de rendre plus fluide à vos utilisateurs. On va venir jouer avec la gestion des espacements et l'alignement des vues.
Le modifcateur .padding()
Text("Hello SwiftUI")
.padding()
.background(Color.yellow)
On ajoute dans notre exemple un padding uniforme autour du texte.
On peut aussi le spécifier :
Text("Padding horizontal")
.padding(.horizontal, 20)
.background(Color.green)
Vous pouvez également utiliser .vertical, .top, .bottom, .leading, .trailing...

Spacer()
Ce composant permet de pousser les éléments au maximum de l'espace disponible. Il créer un vide extensible entre les éléments.
HStack {
Text("Gauche")
Spacer()
Text("Droite")
}
.padding()

Avec le paramètre spacing dans VStack, HStack ou ZStack vous pouvez définir l'espace entre les vues dans le stack :
VStack(spacing: 40) {
Text("Un")
Text("Deux")
Text("Trois")
}
.frame
Il permet de fixer une largeur, hauteur ou les deux.
Text("Avec frame")
.frame(width: 200, height: 100)
.background(Color.orange)
Pour aligner des vues dans un stack nous pouvons contrôler l'alignement global :
VStack(alignment: .leading) {
Text("Titre")
.font(.title)
Text("Sous-titre")
Text("Description")
}
.frame(maxWidth: .infinity, alignment: .leading)
Pour centrer facilement une vue nous pouvons utiliser multilineTextAlignment(.center) combiné avec .frame(maxWidth: .infinity) :
Text("Centré")
.frame(maxWidth: .infinity)
.multilineTextAlignment(.center)
Ajouter du style à notre application
Afin de pimper notre application nous devons passer en revus les éléments proposés par SwiftUI pour styliser ton application.
On a pu le voir dans plusieurs exemples, on peut utiliser .foregroundColor(.nomdelacouleur), par exemple :
Text("Texte coloré")
.foregroundColor(.blue)
Rectangle()
.fill(Color.green)
À savoir que ces couleurs s'adaptent automatiquement aux modes clair/sombre, plutôt sympas :).
Exemples de couleurs système :
.red
,.orange
,.yellow
,.green
,.blue
,.purple
,.pink
,.gray
.primary
/.secondary
(adaptatifs)
On peut créer tes propres couleurs personnalisées, en dur dans le code avec du RGB
Color(red: 0.2, green: 0.6, blue: 0.9)
// dans une extension
extension Color {
static let monBleu = Color(red: 0.15, green: 0.45, blue: 0.75)
}
// pour appeler la couleur après :
Text("Bonjour").foregroundColor(.monBleu)
Depuis les Assets de XCode :
- Va dans les assets
- Clic droit > new color set
- Renomme ta couleur, par exemple BrandColor
- Choisis une couleur depuis l'inspecteur
Rectangle()
.fill(Color("BrandColor"))
Créer un dégradé

Dégradé linéaire
LinearGradient(
colors: [.blue, .purple],
startPoint: .top,
endPoint: .bottom
)
.frame(height: 200)
On peut s'amuser à modifier startPoint et endPoint pour définir la direction du dégradé.
Dégradé radial
RadialGradient(
colors: [.orange, .red],
center: .center,
startRadius: 20,
endRadius: 100
)
.frame(width: 200, height: 200)
Le radial créer un effet de halo autour du centre.
Dégradé angulaire
AngularGradient(
colors: [.yellow, .pink, .purple],
center: .center
)
.frame(width: 200, height: 200)
.clipShape(Circle())
Dégradé 🤝 Texte
On peut utiliser le dégradé comme fond derrière un texte :
ZStack {
LinearGradient(colors: [.blue, .green], startPoint: .leading, endPoint: .trailing)
Text("Dégradé")
.font(.largeTitle)
.bold()
.foregroundColor(.white)
}
.frame(height: 100)
.cornerRadius(12)

Formes géométriques
Rectangle
Rectangle()
.fill(Color.red)
.frame(width: 200, height: 100)

Cercle
Circle()
.stroke(Color.purple, lineWidth: 3)
.frame(width: 120, height: 120)
.shadow(radius: 5)
J'ai ajouté ici quelques modificateurs stroke et shadow pour ajouter des bordures violettes (stroke) et ajouter de l'ombrage (shadow).

Capsule
Capsule()
.fill(Color.orange)
.frame(width: 200, height: 60)

Forme 🤝 Texte
ZStack {
Circle()
.fill(Color.blue)
.frame(width: 100, height: 100)
Text("OK")
.foregroundColor(.white)
.font(.headline)
}

Les modificateurs .clipShape et .overlay pour styliser encore plus.
.clipShape permet de découper une vue selon une forme et .overlay permet de superposer un élément sur un autre.
On va tester justement clipShape autour d'un avatar :
Image("profil")
.resizable()
.scaledToFill()
.frame(width: 120, height: 120)
.clipShape(Circle())
De fait, l'image est "coupée" en cercle, même si l'image est rectangulaire.

Maintenant on va ajouter overlay avec une bordure blanche à notre image et également ajouté de l'ombrage :
Image("profil")
.resizable()
.scaledToFill()
.frame(width: 120, height: 120)
.clipShape(Circle())
.overlay(
Circle().stroke(Color.white, lineWidth: 4)
)
.shadow(radius: 10)

💡Bonus - Ajouter un badge avec .overlay
ZStack(alignment: .topTrailing) {
Image(systemName: "bell.fill")
.font(.system(size: 50))
.padding()
Circle()
.fill(Color.red)
.frame(width: 20, height: 20)
.overlay(
Text("1")
.font(.caption2)
.foregroundColor(.white)
)
.offset(x: 5, y: -5)
}
Parfait pour créer un badge avec une notification :)

Conclusion
Cette première approche de SwiftUI se termine, grâce à cela j'espère que vous avez pu apprendre davantage sur certains composants et modificateurs de base de ce framework. Nous aurions également pu aborder TextField afin de créer des formulaires dans votre application, mais nous pourrons mettre en pratique tout ce que nous avons vu ici dès le prochain tutoriel 😀