mobile-ios-design

Par wshobson · agents

Maîtrisez les Human Interface Guidelines iOS et les patterns SwiftUI pour créer des applications iOS natives. À utiliser lors de la conception d'interfaces iOS, de l'implémentation de vues SwiftUI, ou pour s'assurer que les applications respectent les principes de design d'Apple.

npx skills add https://github.com/wshobson/agents --skill mobile-ios-design

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

  1. Utiliser les couleurs sémantiques : Toujours utiliser .primary, .secondary, .background pour le support automatique du mode clair/sombre
  2. Adopter les SF Symbols : Utiliser les symboles système pour la cohérence et l'accessibilité automatique
  3. Supporter Dynamic Type : Utiliser les polices sémantiques (.body, .headline) au lieu de tailles fixes
  4. Ajouter l'accessibilité : Inclure les modificateurs .accessibilityLabel() et .accessibilityHint()
  5. Respecter les zones sûres : Respecter safeAreaInset et éviter le padding codé en dur aux bords de l'écran
  6. Implémenter la restauration d'état : Utiliser @SceneStorage pour préserver l'état utilisateur
  7. Supporter le multitâche iPad : Concevoir pour split view et slide over
  8. 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/LazyHStack pour les longues listes déroulantes
  • Bugs de navigation : S'assurer que les valeurs NavigationLink sont Hashable
  • 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

Skills similaires