Expert SwiftUI

Utilisez cette compétence pour écrire, réviser ou refactoriser du code SwiftUI pour iOS ou macOS, y compris la gestion d'état et le flux de données `@Observable`, la composition de vues, les mises en page redimensionnables, les zones de sécurité, l'échelle d'affichage, les performances, les listes, l'environnement, la localisation, l'animation, Liquid Glass et la migration d'API. Également utile pour les mises en page iPhone Duo, pliables ou grand écran (`NavigationSplitView` sur grand écran, barre latérale iPhone, réorganisation sur deux colonnes, grilles pliables, `ArrangementView`, `ReservedRegion`), les effets de charnière, les barres verticales, l'initialisation de `@State` ou les diagnostics de propriétés synthétisées, l'ambiguïté `@ContentBuilder`, le glisser-déposer `reorderable`, le `AsyncImage` personnalisé avec `URLSession`, les actions de balayage en dehors des listes, les `alert`/`confirmationDialog` liés à un élément, `ToolbarOverflowMenu`, `AnimatableValues`, les API Document (`Document`/`DocumentReader`), et la capture ou l'analyse de trace Instruments `.trace`.

Qu'est-ce que Expert SwiftUI ?

Cette compétence transforme un agent IA en expert SwiftUI, lui fournissant des règles strictes et des workflows spécialisés pour écrire, réviser et optimiser du code SwiftUI. Elle est conçue pour les développeurs utilisant des agents comme Claude Code, Cursor ou Codex. La compétence garantit la correction via une checklist d'exactitude (par exemple, `@State` privé, identité stable dans `ForEach`, portes `#available`), et améliore les performances via une analyse des traces Instruments (capture de traces, analyse des accrocs, des mises à jour SwiftUI et des graphes de causes). Elle suit un routeur thématique qui oriente l'agent vers des fichiers de référence dédiés pour des sujets spécifiques tels que la gestion d'état, les animations, les listes, les mises en page adaptatives, l'accessibilité, la localisation, et les transitions d'API dépréciées. La compétence encourage la séparation des préoccupations (logique métier vs vues) et suit les directives d'Apple, tout en restant pragmatique sur l'adoption de nouvelles API comme Liquid Glass ou les formats grand écran.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/erumkatzwan/agentic-product-starter/tree/HEAD/apps/ios/.agents/skills/swiftui-expert

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Compétence Expert SwiftUI

Règles de fonctionnement

  • Traiter chaque type View comme une frontière d'invalidation : ne lui donner que les données qu'elle lit et maintenir les dépendances qui changent fréquemment proches de la plus petite sous-arborescence affectée.
  • Rechercher references/latest-apis.md lors de l'écriture, de la révision ou de la migration d'API ; ne consulter que les API pertinentes pour la tâche.
  • Remplacer les API définitivement dépréciées par des équivalents modernes. Pendant le développement de fonctionnalités, signaler les API mollement dépréciées sans les modifier (voir references/soft-deprecation.md).
  • Privilégier les API SwiftUI natives à l'interfaçage UIKit/AppKit, sauf si l'interfaçage est nécessaire.
  • Se concentrer sur la correction et les performances ; ne pas imposer d'architectures spécifiques (MVVM, VIPER, etc.).
  • Encourager la séparation de la logique métier des vues pour la testabilité sans imposer de méthode.
  • Suivre les directives d'interface humaine d'Apple et les patrons de conception d'API.
  • N'adopter Liquid Glass que lorsque l'utilisateur le demande explicitement (voir references/liquid-glass.md).
  • Présenter les optimisations de performance comme des suggestions, pas des exigences.
  • Utiliser le filtrage #available avec des solutions de repli pertinentes pour les API spécifiques à une version.
  • Pour les entrées de mise en page et de rendu, lire la valeur la plus proche de la vue SwiftUI qui la consomme ; ne pas substituer l'état d'écran global du processus.

Flux de travail pour les tâches

Réviser du code SwiftUI existant

  • Lire le code en cours de révision et identifier les sujets applicables.
  • Signaler les API dépréciées (comparer avec references/latest-apis.md) ; remplacer les API définitivement dépréciées, et signaler les API mollement dépréciées sans les réécrire sauf si l'utilisateur a demandé une migration.
  • Exécuter le routeur thématique ci-dessous pour chaque sujet pertinent.
  • Valider le filtrage #available et les chemins de repli pour les fonctionnalités spécifiques à une version.
  • Pour les révisions de code à grande échelle, identifier d'abord des zones d'intérêt plus petites et les présenter une par une ; si l'utilisateur demande une révision de l'ensemble du code, diviser cela en une liste de tâches.

Améliorer du code SwiftUI existant

  • Auditer l'implémentation actuelle par rapport aux sujets du routeur thématique.
  • Remplacer les API définitivement dépréciées par des équivalents modernes de references/latest-apis.md ; signaler les API mollement dépréciées sans les réécrire pendant le développement de fonctionnalités.
  • Refactoriser les chemins chauds pour réduire les mises à jour d'état inutiles.
  • Extraire les corps de vues complexes en sous-vues séparées.
  • Suggérer le sous-échantillonnage d'image lorsque UIImage(data:) est rencontré (optimisation optionnelle, voir references/image-optimization.md).

Implémenter une nouvelle fonctionnalité SwiftUI

  • Concevoir d'abord le flux de données : identifier l'état possédé par rapport à l'état injecté.
  • Structurer les vues pour un diffing optimal (extraire les sous-vues tôt).
  • Appliquer les patrons d'animation corrects (implicite vs explicite, transitions).
  • Utiliser Button pour tous les éléments cliquables ; ajouter un groupement d'accessibilité et des labels.
  • Filtrer les API spécifiques à une version avec #available et fournir des solutions de repli.

Enregistrer une nouvelle trace Instruments

Déclencher lorsque l'utilisateur demande "d'enregistrer une trace", "de profiler l'application", "de capturer une session", etc. Référence complète : references/trace-recording.md.

  1. Confirmer la cible — attacher à une application en cours d'exécution, lancer une application, ou enregistrer tous les processus ? Si l'utilisateur n'a pas précisé, demander. Lister les appareils connectés si utile :
    python3 "${SKILL_DIR}/scripts/record_trace.py" --list-devices
    
  2. Choisir un modèle en fonction du type de cible — Le modèle SwiftUI remplit la voie SwiftUI sur tout appareil réel : un appareil iOS/iPadOS physique ou le Mac hôte. La seule exception est le simulateur iOS, où la voie SwiftUI revient vide — dans ce cas, utiliser --template "Time Profiler" (donne le profileur temporel + blocages, mais pas d'accrocs d'animation). Toujours vérifier --list-devices : type simulators → Time Profiler ; type devices (appareils réels et le Mac hôte) → par défaut SwiftUI. Table de décision complète dans references/trace-recording.md.
  3. Démarrer l'enregistrement. Pour les sessions pilotées par agent où l'utilisateur dit "Je te dirai quand j'aurai fini", démarrer en arrière-plan et utiliser un fichier d'arrêt :
    python3 "${SKILL_DIR}/scripts/record_trace.py" \
        --device "<nom|udid>" --attach "<NomApp>" \
        --stop-file /tmp/stop-trace --output ~/Desktop/session.trace
    
    Pour les sessions interactives, simplement dire à l'utilisateur d'appuyer sur Ctrl+C quand il a terminé.
  4. Signaler l'arrêt — lorsque l'utilisateur dit qu'il a fini d'exercer l'application, touch /tmp/stop-trace. Le script envoie proprement un SIGINT à xctrace et attend jusqu'à 60s la finalisation.
  5. Analyser la trace résultante (passer au flux de travail "Amélioration basée sur les traces" ci-dessous).

Amélioration basée sur les traces (fourniture d'un fichier .trace Instruments)

Déclencher chaque fois que la requête de l'utilisateur fait référence à un fichier .trace. Un fichier source SwiftUI cible est optionnel — s'il est donné, citer des lignes spécifiques ; sinon, recommander où chercher en fonction des noms de vues et des symboles que la trace révèle déjà.

Référence complète : references/trace-analysis.md.

Blocages : si xctrace help liste triage (Xcode 27.2 le fait), commencer par xctrace triage <trace> --style hangs, puis approfondir avec xctrace show. L'analyseur fourni reste l'outil pour les accrocs, les mises à jour SwiftUI, le graphe des causes et les fenêtres de logs ou signposts.

Résumé du modèle de composition de l'analyseur :

  1. Délimiter l'analyse. Se demander : l'utilisateur veut-il la trace entière, ou une partie ?
    • "concentrer sur X / après X / entre X et Y / pendant X" → résoudre d'abord une fenêtre (voir étape 2).
    • Aucune indication de délimitation → analyser la trace entière.
  2. Résoudre une fenêtre (uniquement si l'utilisateur a délimité). L'analyseur expose deux modes de découverte :
    # Trouver un log qui marque le début/fin de la région d'intérêt :
    python3 "${SKILL_DIR}/scripts/analyze_trace.py" --trace <chemin> \
        --list-logs --log-message-contains "flux chargé" --log-limit 5
    # Ou lister les intervalles os_signpost (début/fin appariés), filtrables par nom :
    python3 "${SKILL_DIR}/scripts/analyze_trace.py" --trace <chemin> \
        --list-signposts --signpost-name-contains "ImageDecode"
    
    Les deux modes acceptent --window START_MS:END_MS pour délimiter la découverte. Choisir le time_ms (pour les logs) ou start_ms/end_ms (pour les signposts) qui correspondent à la description de l'utilisateur. Construire une fenêtre comme --window 10400:11700.
  3. Lancer l'analyse principale (avec ou sans --window) :
    python3 "${SKILL_DIR}/scripts/analyze_trace.py" --trace <chemin> \
        --json-only --top 10 [--window START_MS:END_MS]
    
  4. Interpréter avec references/trace-analysis.md — diagnostics clés :
    • main_running_coverage_pct dans chaque corrélation (<25 % = bloqué ; ≥75 % = lié au CPU).
    • swiftui-causes.top_sources révèle pourquoi les mises à jour continuent — les sources à haut nombre d'arêtes comme UserDefaultObserver.send() ou les entrées EnvironmentWriter larges sont des bugs d'invalidation structurelle. En corriger un effondre souvent plusieurs vues chaudes en aval.
  5. Lorsqu'une vue spécifique est coûteuse, demander qui l'invalide. Utiliser --fanin-for "<nom de vue>" pour obtenir la liste classée des nœuds sources qui entraînent les mises à jour.
  6. Optionnellement, ancrer dans le source. Si l'utilisateur a pointé un fichier, le lire et faire correspondre les noms de vues / symboles de code utilisateur avec les identifiants présents. Sinon, recommander les fichiers à ouvrir en fonction des noms de vues rapportés par SwiftUI.
  7. Retourner un plan priorisé. Citer des preuves (pourcentage de couverture, symbole chaud, vue superposée, horodatage de log, arêtes du graphe de causes) et router chaque recommandation vers une référence du routeur thématique.
  8. Ne modifier le code que si l'utilisateur a demandé des modifications.

Routeur thématique

Consulter le fichier de référence pour chaque sujet pertinent à la tâche en cours :

SujetRéférence
Gestion d'étatreferences/state-management.md
Environnement et @Entry, y compris les avertissements "Storing a closure/class type in '@Entry var'"references/environment-patterns.md
Composition de vuesreferences/view-structure.md
Modificateurs de vue et identitéreferences/modifier-patterns.md
Performancesreferences/performance-patterns.md
Listes et ForEachreferences/list-patterns.md
Mise en page redimensionnable, zones de sécurité, réorganisation sur deux colonnes, grilles pliables, arrangements et régions réservéesreferences/layout-best-practices.md
Écrans iPhone Duo, pliables ou grand écran (lire en premier pour choisir la technique)references/iphone-duo.md
Feuilles, navigation, NavigationSplitView sur grand écran, et barre d'onglets/barre latérale (sidebarAdaptable)references/sheet-navigation-patterns.md
ScrollView, position de défilement et géométrie de défilementreferences/scroll-patterns.md
Gestion du focusreferences/focus-patterns.md
Animations (bases)references/animation-basics.md
Animations (transitions)references/animation-transitions.md
Animations (avancé)references/animation-advanced.md
Accessibilitéreferences/accessibility-patterns.md
Swift Chartsreferences/charts.md
Accessibilité des graphiquesreferences/charts-accessibility.md
Optimisation d'image et échelle d'affichagereferences/image-optimization.md
Barres d'outilsreferences/toolbar-patterns.md
Applications basées sur des documentsreferences/document-apps.md
WebKitreferences/webkit-integration.md
Édition de texte styliséreferences/styled-text-editing.md
Liquid Glass (iOS 26+)references/liquid-glass.md
Scènes macOSreferences/macos-scenes.md
Style de fenêtre macOSreferences/macos-window-styling.md
Vues macOSreferences/macos-views.md
Patrons de textereferences/text-patterns.md
Localisationreferences/localization.md
Recherche d'API dépréciéereferences/latest-apis.md
Gestion des API mollement dépréciéesreferences/soft-deprecation.md
Aperçusreferences/previews.md
Analyse de trace Instrumentsreferences/trace-analysis.md
Enregistrement de trace Instrumentsreferences/trace-recording.md

Checklist d'exactitude

Ce sont des règles strictes — leur violation est toujours un bug :

  • Les propriétés @State sont private
  • @Binding uniquement là où un enfant modifie l'état du parent
  • Les entrées modifiables appartenant au parent ne sont pas stockées comme @State/@StateObject ; les graines d'état intentionnelles sont documentées comme ponctuelles
  • @StateObject pour les objets appartenant à la vue ; @ObservedObject pour les objets injectés
  • iOS 17+ : @State avec @Observable ; @Bindable pour les observables injectés nécessitant des liaisons
  • ForEach utilise une identité stable (jamais .indices/\.offset ; l'identité survit à la vue et n'est pas dérivée d'un contenu mutable)
  • Nombre constant de vues par élément ForEach ; les lignes List sont unaire
  • Aucune fermeture stockée dans les clés @Environment/@FocusedValue personnalisées
  • Les valeurs par défaut de @Entry personnalisées sont stables (pas d'expressions Model()/Date()/UUID())
  • L'échelle d'affichage SwiftUI provient de @Environment(\.displayScale), pas de l'état d'écran global
  • Les contenus de zone de sécurité n'appliquent pas deux fois GeometryProxy.safeAreaInsets
  • .animation(_:value:) inclut toujours le paramètre value
  • Les propriétés @FocusState sont private
  • Pas d'écritures redondantes @FocusState dans les gestionnaires de tap sur les vues .focusable()
  • Les API spécifiques à une version sont filtrées avec #available et ont des solutions de repli pertinentes
  • import Charts présent dans les fichiers utilisant des types de graphiques
  • Les aperçus utilisent des données mock auto-contenues ; aucune dépendance aux services en direct ou au réseau

Skills associés