Conception iOS mobile
Maîtrisez les directives d'interface utilisateur iOS (HIG) et les patterns SwiftUI pour créer des applications iOS polies qui s'intègrent naturellement aux plateformes Apple.
Quand utiliser cette compétence
- Concevoir des interfaces d'applications iOS en suivant les HIG Apple
- Créer des vues et des mises en page SwiftUI
- Implémenter les patterns de navigation iOS (NavigationStack, TabView, sheets)
- Créer des mises en page adaptatives pour iPhone et iPad
- Utiliser les SF Symbols et la typographie système
- Construire des interfaces iOS accessibles
- Implémenter les gestes et interactions spécifiques à iOS
- Concevoir pour Dynamic Type et Dark Mode
Concepts fondamentaux
1. Principes des directives d'interface utilisateur
Clarté : Le contenu est lisible, les icônes sont précises, les ornements sont subtils Déférence : L'interface aide les utilisateurs à comprendre le contenu sans le concurrencer Profondeur : Les calques visuels et le mouvement transmettent la hiérarchie et permettent la navigation
Considérations liées à la plateforme :
- iOS : Tactile en priorité, affichages compacts, orientation portrait
- iPadOS : Canevas plus grand, multitâche, support du pointeur
- visionOS : Informatique spatiale, entrée oculaire/manuelle
2. Système de mise en page SwiftUI
Mises en page basées sur des piles :
// Pile verticale avec alignement
VStack(alignment: .leading, spacing: 12) {
Text("Title")
.font(.headline)
Text("Subtitle")
.font(.subheadline)
.foregroundStyle(.secondary)
}
// Pile horizontale avec espacement flexible
HStack {
Image(systemName: "star.fill")
Text("Featured")
Spacer()
Text("View All")
.foregroundStyle(.blue)
}
Mises en page en grille :
// Grille adaptative qui remplit la largeur disponible
LazyVGrid(columns: [
GridItem(.adaptive(minimum: 150, maximum: 200))
], spacing: 16) {
ForEach(items) { item in
ItemCard(item: item)
}
}
// Grille à colonnes fixes
LazyVGrid(columns: [
GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible())
], spacing: 12) {
ForEach(items) { item in
ItemThumbnail(item: item)
}
}
3. Patterns de navigation
NavigationStack (iOS 16+) :
struct ContentView: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
List(items) { item in
NavigationLink(value: item) {
ItemRow(item: item)
}
}
.navigationTitle("Items")
.navigationDestination(for: Item.self) { item in
ItemDetailView(item: item)
}
}
}
}
TabView (iOS 18+) :
struct MainTabView: View {
@State private var selectedTab = 0
var body: some View {
TabView(selection: $selectedTab) {
Tab("Home", systemImage: "house", value: 0) {
HomeView()
}
Tab("Search", systemImage: "magnifyingglass", value: 1) {
SearchView()
}
Tab("Profile", systemImage: "person", value: 2) {
ProfileView()
}
}
}
}
4. Intégration système
SF Symbols :
// Symbol basique
Image(systemName: "heart.fill")
.foregroundStyle(.red)
// Symbol avec mode de rendu
Image(systemName: "cloud.sun.fill")
.symbolRenderingMode(.multicolor)
// Variable symbol (iOS 16+)
Image(systemName: "speaker.wave.3.fill", variableValue: volume)
// Symbol effect (iOS 17+)
Image(systemName: "bell.fill")
.symbolEffect(.bounce, value: notificationCount)
Dynamic Type :
// Utiliser les polices sémantiques
Text("Headline")
.font(.headline)
Text("Body text that scales with user preferences")
.font(.body)
// Police personnalisée qui respecte Dynamic Type
Text("Custom")
.font(.custom("Avenir", size: 17, relativeTo: .body))
5. Conception visuelle
Couleurs et matériaux :
// Couleurs sémantiques qui s'adaptent au mode clair/sombre
Text("Primary")
.foregroundStyle(.primary)
Text("Secondary")
.foregroundStyle(.secondary)
// Matériaux système pour les effets de flou
Rectangle()
.fill(.ultraThinMaterial)
.frame(height: 100)
// Matériaux vibrants pour les superpositions
Text("Overlay")
.padding()
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 12))
Ombres et profondeur :
// Ombre standard pour carte
RoundedRectangle(cornerRadius: 16)
.fill(.background)
.shadow(color: .black.opacity(0.1), radius: 8, y: 4)
// Apparence élevée
.shadow(radius: 2, y: 1)
.shadow(radius: 8, y: 4)
Composant de démarrage rapide
import SwiftUI
struct FeatureCard: View {
let title: String
let description: String
let systemImage: String
var body: some View {
HStack(spacing: 16) {
Image(systemName: systemImage)
.font(.title)
.foregroundStyle(.blue)
.frame(width: 44, height: 44)
.background(.blue.opacity(0.1), in: Circle())
VStack(alignment: .leading, spacing: 4) {
Text(title)
.font(.headline)
Text(description)
.font(.subheadline)
.foregroundStyle(.secondary)
.lineLimit(2)
}
Spacer()
Image(systemName: "chevron.right")
.foregroundStyle(.tertiary)
}
.padding()
.background(.background, in: RoundedRectangle(cornerRadius: 12))
.shadow(color: .black.opacity(0.05), radius: 4, y: 2)
}
}
Bonnes pratiques
- Utiliser les couleurs sémantiques : Toujours utiliser
.primary,.secondary,.backgroundpour le support automatique du mode clair/sombre - Adopter les SF Symbols : Utiliser les symboles système pour la cohérence et l'accessibilité automatique
- Supporter Dynamic Type : Utiliser les polices sémantiques (
.body,.headline) au lieu de tailles fixes - Ajouter l'accessibilité : Inclure les modificateurs
.accessibilityLabel()et.accessibilityHint() - Respecter les zones sûres : Respecter
safeAreaInsetet éviter le padding codé en dur aux bords de l'écran - Implémenter la restauration d'état : Utiliser
@SceneStoragepour préserver l'état utilisateur - Supporter le multitâche iPad : Concevoir pour split view et slide over
- Tester sur appareil : Le simulateur ne capture pas la pleine expérience haptique et de performance
Problèmes courants
- Mise en page cassée : Utiliser
.fixedSize()avec parcimonie ; préférer les mises en page flexibles - Problèmes de performance : Utiliser
LazyVStack/LazyHStackpour les longues listes déroulantes - Bugs de navigation : S'assurer que les valeurs
NavigationLinksontHashable - Problèmes de Dark Mode : Éviter les couleurs codées en dur ; utiliser les couleurs sémantiques ou du catalogue d'assets
- Échecs d'accessibilité : Tester avec VoiceOver activé
- Fuites mémoire : Faire attention aux cycles de références fortes dans les closures