Aller au contenu

Simulateurs iOS et Xcode

Xcode et le simulateur iOS sont souvent les plus gros consommateurs d'espace disque sur le Mac d'un développeur React Native ou iOS, et l'essentiel de cet espace reste invisible : des caches de build nommés d'après des hashs, des simulateurs que personne ne se souvient d'avoir créés, des runtimes pour des versions d'iOS que vous ne testez plus, et des enregistrements d'écran enfouis au fond des conteneurs des simulateurs.

lu-cleaner répartit tout cela en deux catégories :

Catégorie Contenu
xcode DerivedData, archives, symboles de device support, caches de Xcode, CocoaPods, SwiftPM, Carthage, fastlane
simulators appareils et runtimes des simulateurs, enregistrements XCTest, journaux et caches des simulateurs, ensembles d'appareils gérés par Xcode

Les dossiers propres à chaque projet, comme ios/Pods et ios/build, sont des artefacts de projet, traités dans Projets React Native.

Fenêtre de terminal
lu-cleaner scan -c xcode,simulators # ce qui prend de la place ; rien n'est modifié
lu-cleaner clean -c xcode,simulators # sélecteur : rien n'est sélectionné, appuyez sur a pour les éléments recommandés
lu-cleaner devices # simulateurs et émulateurs Android uniquement (a pour la sélection intelligente)

Un scan typique ressemble à ceci (tailles données à titre d'exemple) :

iOS Simulators 50.2 GB · 6 items · ★ 35.0 GB recommended NAME SIZE AGE RISK RECO iPhone 16 Pro · iOS 18.5 31.6 GB 3d caution XCTest recordings · iPhone 16 Pro 24.8 GB 3d safe ★ iOS 18.5 runtime (22F77) 8.40 GB now moderate ! used by 3 simulator(s) — deleting it makes them unavailable iOS 17.5 runtime (21F79) 7.90 GB 5mo moderate ★ iPhone 14 · iOS 16.4 (unavailable) 2.30 GB 8mo safe ★ iPad Air · iOS 18.5 1.40 GB 2h info ! booted — shut it down before deleting it

Xcode 19.5 GB · 5 items · ★ 14.0 GB recommended NAME SIZE AGE RISK RECO MyApp (workspace gone) 6.20 GB 5w safe ★ MyApp 4.90 GB 2h safe ★ MyApp 2.4.0 (318) 3.10 GB 4mo caution ! latest archive of this app — keep it (or its dSYMs) to symbolicate crashes iOS 17.6.1 (21G93) 2.90 GB 9mo moderate ★ iOS 18.6 (22G86) 2.40 GB 2w moderate ! newest iOS symbols — kept for on-device debugging

★ marque ce que choisit la sélection intelligente. Les lignes qui commencent par ! sont des avertissements : un élément qui porte un avertissement n'est jamais recommandé. info dans la colonne du risque signifie que l'élément est listé à titre d'information et ne peut pas être sélectionné (rapport seul, ou bloqué pour le moment, comme un simulateur démarré).

Xcode conserve les produits de build, l'index et les journaux de build de chaque workspace dans ~/Library/Developer/Xcode/DerivedData/<Project>-<hash>. Le hash est dérivé du chemin du workspace : chaque clone et chaque worktree git d'un projet obtient donc son propre dossier, souvent de plusieurs Go. Avec des agents IA qui créent un worktree par tâche, DerivedData grossit vite.

lu-cleaner affiche un élément par dossier et le nomme d'après le workspace enregistré dans le info.plist du dossier, pour que vous n'ayez jamais à décoder le hash :

  • MyApp : le cache de build d'un workspace existant. La note de l'élément indique lequel, par exemple ~/dev/my-app/ios/MyApp.xcworkspace ou ~/.codex/worktrees/a1b2/my-app/ios/MyApp.xcworkspace.
  • MyApp (workspace gone) : le workspace n'existe plus (worktree supprimé, clone effacé). Rien ne réutilisera jamais ce cache.

Les deux sont safe : le prochain build recrée tout, au prix d'une recompilation complète et d'une réindexation. Comme DerivedData n'est qu'un cache, la sélection intelligente recommande tous les dossiers, y compris celui du projet que vous compilez aujourd'hui. Si vous voulez conserver les builds incrémentaux, désélectionnez ce projet après avoir appuyé sur a dans le sélecteur, ou ne ciblez que les dossiers que vous n'avez pas compilés depuis un moment :

Fenêtre de terminal
lu-cleaner clean --yes -k xcode-derived-data --older-than 14d --dry-run

Quelques précisions :

  • La dernière utilisation provient du LastAccessedDate enregistré par Xcode, ou à défaut du journal de build, du produit de build ou de l'écriture d'index la plus récente : les builds xcodebuild lancés en ligne de commande comptent donc aussi.
  • Emplacement personnalisé. Si vous avez déplacé DerivedData dans Xcode › Settings › Locations, lu-cleaner lit ce réglage et analyse les deux emplacements. Les emplacements relatifs, propres à chaque workspace, ne peuvent pas être analysés globalement.
  • Cache de modules partagé. ModuleCache.noindex et SymbolCache.noindex contiennent des modules Clang et Swift précompilés, partagés par tous les projets. Ils sont safe ; le premier build qui suit est plus lent.
  • « Disparu » signifie « dont la disparition est prouvée ». Un workspace situé sur un disque externe non monté n'est pas considéré comme supprimé : lu-cleaner n'ajoute (workspace gone) que s'il peut prouver que le chemin n'existe plus.
  • Les éléments DerivedData sont ignorés tant que Xcode ou xcodebuild tourne.

Product › Archive écrit un .xcarchive dans ~/Library/Developer/Xcode/Archives/<date>/. Il contient le binaire livré et ses dSYMs, les symboles de débogage nécessaires pour symboliquer les rapports de crash de ce build précis. Une archive ne peut pas être reconstruite à l'identique : un nouveau build reçoit de nouveaux UUID de binaire, et les rapports de crash de l'ancien build restent illisibles.

C'est pourquoi les archives reçoivent le traitement le plus strict de cette catégorie :

  • Risque caution. Les archives ne sont jamais recommandées, et clean --yes les laisse de côté sauf si vous passez --risk caution.
  • Déplacées vers la Corbeille, pas supprimées. Vous pouvez encore en remettre une en place, mais l'espace n'est libéré qu'une fois la Corbeille vidée.
  • L'archive la plus récente de chaque app est signalée. L'archive la plus récente de chaque bundle identifier porte l'avertissement latest archive of this app — keep it (or its dSYMs) to symbolicate crashes.

Les éléments sont nommés d'après l'app, sa version et son numéro de build, par exemple MyApp 2.4.0 (318), et sont ignorés tant que Xcode tourne.

Quand vous lancez une app sur un appareil physique, Xcode copie les symboles de débogage de la version d'OS de l'appareil dans ~/Library/Developer/Xcode/iOS DeviceSupport/<version> (<build>). Cela représente 2 à 6 Go par version d'OS, et un nouveau dossier apparaît chaque fois qu'un appareil sur lequel vous déboguez reçoit une mise à jour. watchOS, tvOS, visionOS et macOS ont leurs propres dossiers … DeviceSupport.

  • La version la plus récente de chaque plateforme est conservée. Elle porte l'avertissement newest iOS symbols — kept for on-device debugging et n'est jamais recommandée.
  • Les versions plus anciennes sont moderate et recommandées une fois périmées (inutilisées depuis plus de stale_after, 14 jours par défaut).
  • Coût : la prochaine fois que vous déboguez sur un appareil qui utilise cette version d'OS, Xcode copie de nouveau les symboles, ce qui prend plusieurs minutes.

Ces emplacements fixes proviennent du catalogue, qui liste les globs exacts.

Élément Emplacement Risque Remarques
Caches de l'application Xcode ~/Library/Caches/com.apple.dt.* safe caches de Xcode, xcodebuild et Instruments
Produits d'installation ~/Library/Developer/Xcode/Products/* safe sortie de Build For › Installing
Cache de la documentation ~/Library/Developer/Xcode/DocumentationCache/* et DocumentationIndex/* safe téléchargé à nouveau à l'ouverture de la fenêtre de documentation
Fichiers de préparation des exports $TMPDIR/XcodeDistPipeline.*, $TMPDIR/*.xcdistributionlogs safe seulement au-delà de 24 heures
Téléchargements de composants ~/Library/Developer/DVTDownloads/* moderate zone de transit ; les composants installés ne sont pas touchés
Journaux de crash des appareils ~/Library/Developer/Xcode/iOS Device Logs (et watchOS) caution les appareils purgent leurs propres journaux de crash, donc ces copies sont souvent les seules qui restent ; jamais recommandés
Toolchain Metal exécute xcodebuild -deleteComponent metalToolchain moderate nécessaire uniquement pour compiler des fichiers .metal ; jamais recommandée
Cache de téléchargement de CocoaPods ~/Library/Caches/CocoaPods safe équivaut à pod cache clean --all
Index trunk de CocoaPods ~/.cocoapods/repos/trunk moderate retéléchargé à la demande ; les dépôts de specs privés ne sont pas touchés
Ancien dépôt master de CocoaPods ~/.cocoapods/repos/master moderate clone git complet du dépôt Specs, inutilisé depuis CocoaPods 1.8
Cache SwiftPM ~/Library/Caches/org.swift.swiftpm safe équivaut à swift package purge-cache
Cache Carthage ~/Library/Caches/org.carthage.CarthageKit moderate carthage bootstrap le télécharge de nouveau (lentement)
Caches de fastlane ~/Library/Caches/tools.fastlane, ~/.fastlane/frameit moderate les cookies de session de ~/.fastlane/spaceship ne sont pas touchés

Les installations de Xcode autres que celle qui est sélectionnée (xcode-select -p), trouvées dans /Applications et ~/Applications, sont listées avec leur taille mais jamais supprimées : désinstaller un Xcode relève de votre décision, et un projet peut encore en avoir besoin. La note suggère xcodes uninstall <version> ou de mettre l'application à la Corbeille. Cette vérification est ignorée quand ce sont les Command Line Tools qui sont sélectionnés au lieu d'un Xcode, car lu-cleaner ne peut alors pas savoir quel Xcode vous utilisez.

lu-cleaner lit l'état des simulateurs avec xcrun simctl list -j et xcrun simctl runtime list -j : noms, runtimes, état de démarrage et dernière utilisation. Si xcrun est absent, ou si seuls les Command Line Tools sont sélectionnés, la partie simulateurs du scan ne trouve rien.

Chaque simulateur forme un élément, par exemple iPhone 16 Pro · iOS 18.5. Il est supprimé avec xcrun simctl delete <udid>, la méthode de suppression propre à CoreSimulator, afin que la liste des appareils de Xcode reste cohérente. Le risque dépend de son contenu :

Simulateur Risque Sélection intelligente
Des apps sont installées caution jamais
Aucune app (ou seulement des runners de tests UI, *.xctrunner) moderate s'il est arrêté et inutilisé depuis plus de stale_after
Jamais démarré (appareils par défaut de Xcode) moderate jamais
Démarré, ou dans un autre état transitoire comme ci-dessus ne peut pas être sélectionné

Pourquoi ces règles :

  • Des apps signifient des données. Supprimer un simulateur qui contient des apps fait perdre leurs données, leurs sessions de connexion et leurs réglages, et vous oblige à réinstaller votre build de développement. Pour effacer le contenu d'un simulateur tout en gardant l'appareil, lancez vous-même xcrun simctl erase <udid>.
  • Les appareils jamais démarrés ne pèsent presque rien. Les supprimer libère peu d'espace et les retire des destinations d'exécution de Xcode.
  • Les simulateurs démarrés sont en cours d'utilisation. L'application Simulator et les apps que vous testez gardent leurs fichiers ouverts. lu-cleaner revérifie aussi l'état juste avant la suppression : un simulateur démarré après le scan est ignoré avec simulator … is booted now — shut it down first.

Les simulateurs au nom personnalisé (différent de leur type d'appareil) sont signalés dans la note : ils ont généralement été créés par un script ou par un agent IA pour la QA.

Les simulateurs dont le runtime a été supprimé, ou n'est pas pris en charge par le Xcode sélectionné, ne peuvent plus démarrer. Chacun constitue son propre élément, par exemple iPhone 14 · iOS 16.4 (unavailable), nettoyé avec xcrun simctl delete <udid> pour ce seul appareil. lu-cleaner ne lance jamais xcrun simctl delete unavailable : cette commande supprimerait aussi des appareils qui ne sont inutilisables que pour le moment.

Simulateur indisponible Risque Sélection intelligente
Son runtime a disparu de façon avérée, et il ne contient aucune app safe oui
Il contient des apps avec leurs données caution jamais : réinstaller son runtime les ferait revenir
Il peut revenir : son runtime est encore installé ou présent sur le disque (dans un autre Xcode, par exemple), un autre Xcode est sélectionné, ou l'image du runtime n'est pas montée après une mise à jour de macOS caution, avec un avertissement qui en donne la raison jamais

Juste avant la suppression, lu-cleaner interroge de nouveau simctl : un appareil redevenu disponible, qui a changé de runtime ou qui a été démarré depuis le scan est ignoré.

Il arrive qu'un dossier de ~/Library/Developer/CoreSimulator/Devices/ soit inconnu de simctl : son device.plist est absent ou invalide, il est marqué comme supprimé, ou son runtime n'est plus installé. Un tel dossier ne peut être ni démarré ni listé, et simctl ne peut pas le supprimer : lu-cleaner supprime donc lui-même le dossier.

Comme cette opération contourne simctl, les vérifications sont prudentes :

  • les orphelins ne sont recherchés que si simctl liste au moins un appareil dans ce même dossier, ce qui prouve que la réponse de simctl porte bien sur lui ;
  • un appareil bien formé, dont le runtime est installé, n'est jamais considéré comme orphelin, même si simctl ne l'a pas listé ;
  • les dossiers modifiés au cours des dernières 24 heures sont ignorés, car ils sont peut-être en cours de création ;
  • les orphelins sont moderate et recommandés après 7 jours sans modification. Les éventuelles données d'app restantes sont nommées dans la note.

Sur les machines qui exécutent des tests UI, c'est souvent le plus gros élément de tous. Pendant l'automatisation XCUITest (xcodebuild test, Maestro, agent-device, argent…), le démon testmanagerd écrit des enregistrements d'écran à l'intérieur du simulateur, sous :

~/Library/Developer/CoreSimulator/Devices/<UDID>/data/Containers/Data/InternalDaemon/<uuid>/tmp/Attachments/

Rien ne les lit ni ne les supprime après l'exécution, et Xcode ne les affiche pas. Plusieurs dizaines de Go sur un seul simulateur, c'est courant.

  • Un élément safe par simulateur : XCTest recordings · iPhone 16 Pro. Seuls les conteneurs qui appartiennent à com.apple.testmanagerd sont pris en compte.
  • Seuls les enregistrements sont supprimés. Le dossier Attachments, le simulateur et ses apps restent en place.
  • Les fichiers partiels *.sb-* laissés par des écritures interrompues sont comptés dans la note.
  • L'élément est recommandé quand le simulateur est arrêté. Tant que celui-ci est démarré, l'élément porte a UI test may still be recording et n'est pas recommandé. Il est ignoré tant que xcodebuild tourne.

L'élément du simulateur lui-même indique Its size includes the XCTest recordings listed separately: clean those first. Dans la plupart des cas, vous voudrez garder le simulateur et supprimer uniquement les enregistrements. Si vous sélectionnez les deux, la suppression du simulateur couvre déjà les enregistrements, et lu-cleaner n'exécute que celle-ci.

Pour ne nettoyer que les enregistrements depuis un script :

Fenêtre de terminal
lu-cleaner clean --yes -k ios-simulator-attachments --dry-run
Élément Type (-k) Risque Description
Journaux unifiés des simulateurs ios-simulator-logs safe archives os_log (fichiers tracev3) des simulateurs arrêtés ; seuls les fichiers sont supprimés, et la journalisation reprend au démarrage suivant
Caches système des simulateurs ios-simulator-caches moderate caches d'analyse des médias, de symbolication, de Plans et de suggestions des simulateurs inutilisés depuis au moins 14 jours ; le premier démarrage qui suit est plus lent
Caches de CoreSimulator coresimulator-caches safe ~/Library/Developer/CoreSimulator/Caches et Temp ; ignorés tant que l'application Simulator tourne
Journaux de CoreSimulator apple-coresimulator-logs safe journaux côté hôte dans ~/Library/Logs/CoreSimulator/*, sans écriture depuis une semaine
Copies temporaires du device set apple-simulator-device-set-tmp safe restes device_set.plist.sb-* d'écritures interrompues ; le registre lui-même n'est jamais touché

Les éléments « journaux unifiés » et « caches système » revérifient juste avant le nettoyage que leurs simulateurs sont toujours arrêtés.

Xcode conserve des simulateurs supplémentaires en dehors de l'ensemble d'appareils par défaut :

Ensemble Emplacement
SwiftUI Previews ~/Library/Developer/Xcode/UserData/Previews/Simulator Devices
Interface Builder ~/Library/Developer/Xcode/UserData/IB Support/Simulator Devices
Clones XCTest (tests parallèles) ~/Library/Developer/XCTestDevices
Playgrounds ~/Library/Developer/XCPGDevices

Chaque ensemble de plus de 1 Mo forme un élément safe, nettoyé avec xcrun simctl --set <dir> delete all. Xcode recrée ces appareils la prochaine fois qu'une preview, un storyboard, un test parallèle ou un playground en a besoin. Ils sont ignorés tant que Xcode tourne.

Un runtime de simulateur est une image disque de plusieurs Go, gérée par macOS dans le stockage système. lu-cleaner ne touche jamais directement à ces fichiers : il demande à CoreSimulator de supprimer le runtime avec xcrun simctl runtime delete <identifier>, et affiche la taille indiquée par simctl.

Runtime Traitement
Fourni avec Xcode rapport seul : il disparaît avec ce Xcode
Utilisé par des simulateurs avertissement used by N simulator(s) — deleting it makes them unavailable
Le plus récent de sa plateforme avertissement newest iOS runtime — needed to run iOS simulators
Parmi les keep_latest runtimes les plus récents de sa plateforme (seulement si vous montez keep_latest au-dessus de 1) jamais recommandé
Inutilisé, alors qu'un runtime plus récent de la même plateforme est installé recommandé

Les runtimes sont moderate : en retélécharger un (environ 8 Go) prend du temps, depuis Xcode › Settings › Components ou avec xcodebuild -downloadPlatform iOS. Ils sont ignorés tant que Xcode tourne. Si vous supprimez un runtime que des simulateurs utilisent encore, ceux-ci deviennent indisponibles (et apparaissent comme éléments … (unavailable) au scan suivant) ; simctl arrête ceux qui sont démarrés.

Le garde-fou de sécurité ne supprime que dans votre dossier personnel et dans votre dossier temporaire utilisateur, et lu-cleaner n'exécute jamais sudo. Tout le reste est listé pour que vous en connaissiez l'existence, avec les instructions pour le supprimer vous-même :

Élément Pourquoi il est en rapport seul Que faire
Caches dyld de simulateur périmés dans /Library/Developer/CoreSimulator/Caches/dyld/ ils appartiennent à root les caches construits pour un build de macOS plus ancien, ou pour un runtime qui n'est plus installé, ne servent plus jamais ; la note donne la commande sudo rm -rf '<path>' exacte
Installations supplémentaires de Xcode hors de votre dossier personnel, et désinstaller Xcode relève de votre décision xcodes uninstall <version>, ou mettre l'application à la Corbeille
Runtimes fournis avec Xcode ils font partie de l'installation de Xcode supprimés en même temps que ce Xcode
Tout ce qui se trouve sur un autre volume le supprimer ne libère rien sur le disque interne affiché avec on external volume — no internal gain
  1. Quittez Xcode et arrêtez tous les simulateurs :

    Fenêtre de terminal
    xcrun simctl shutdown all
  2. Passez en revue ce qui est présent, avec tous les éléments listés :

    Fenêtre de terminal
    lu-cleaner scan -c xcode,simulators --all
  3. Ouvrez le sélecteur. Rien n'est encore sélectionné : appuyez sur a pour sélectionner les éléments recommandés, ou choisissez avec space. Ouvrez chaque catégorie avec enter, désélectionnez ce que vous voulez garder (par exemple le DerivedData de votre projet en cours), puis appuyez sur d pour nettoyer.

    Fenêtre de terminal
    lu-cleaner clean -c xcode,simulators
  4. Si l'espace libre n'a pas augmenté comme prévu, lancez lu-cleaner doctor. Les archives ne libèrent de l'espace qu'une fois la Corbeille vidée ; pour les autres causes, consultez Pourquoi l'espace libéré n'apparaît pas.

Les touches du sélecteur sont listées dans Raccourcis clavier.

Fenêtre de terminal
# Le plan que la sélection intelligente exécuterait ; rien n'est supprimé
lu-cleaner clean --yes --smart -c xcode,simulators --dry-run
# Uniquement les enregistrements XCTest
lu-cleaner clean --yes -k ios-simulator-attachments
# DerivedData sans build depuis un mois
lu-cleaner clean --yes -k xcode-derived-data --older-than 30d
# Runtimes inutilisés et simulateurs indisponibles, uniquement ceux recommandés
lu-cleaner clean --yes --smart -k ios-simulator-runtime,ios-simulators-unavailable

Voici les types que vous pouvez passer à -k. L'identifiant de fournisseur apple sélectionne d'un coup tous les types du scanner Xcode et simulateurs (avec clean --yes, ajoutez -c ou --smart : il couvre deux catégories) ; les types du catalogue (apple-*) sont reconnus par leur propre identifiant.

Type Élément
xcode-derived-data DerivedData d'un workspace
xcode-module-cache, apple-xcode-module-cache cache de modules partagé (emplacement personnalisé et emplacement par défaut)
xcode-archive un .xcarchive
xcode-device-support symboles de débogage d'une version d'OS d'appareil
xcode-metal-toolchain le composant toolchain Metal
xcode-app installation supplémentaire de Xcode (rapport seul)
ios-simulator un appareil simulé
ios-simulators-unavailable un simulateur indisponible
ios-simulator-orphan un dossier d'appareil inconnu de simctl
ios-simulator-attachments enregistrements XCTest d'un simulateur
ios-simulator-logs, ios-simulator-caches journaux unifiés, caches système dans les simulateurs
ios-simulator-device-set un ensemble d'appareils Previews, Interface Builder, XCTest ou Playground
ios-simulator-runtime un runtime de simulateur
ios-simulator-dyld-cache cache dyld périmé (rapport seul)
coresimulator-caches caches CoreSimulator de l'utilisateur

Les entrées du catalogue (apple-*) sont listées dans le catalogue. La sortie --json de scan expose le même champ kind, ainsi que des métadonnées propres à chaque élément comme udid, runtime, workspace ou orphan ; voir Sortie JSON.