La soumission renvoie « ITMS-90870 Missing launch screen » alors que le projet démarre encore correctement sur l’appareil.
La correction la plus rapide est de vérifier le SDK utilisé, d’ajouter une déclaration de lancement reconnue dans l’Info.plist final, puis de contrôler l’Archive Release avant un nouvel envoi. Une chaîne de production encore compilée avec le SDK iOS 26 peut rester en place provisoirement, mais nous recommandons de préparer immédiatement une branche Xcode 27 séparée.
Dernière mise à jour : 27 août 2026. Les règles de lancement et la capacité d’envoi de Xcode 27 Beta 5 ont été revérifiées dans les notes de version iOS et iPadOS 27, la note technique TN3208 et les notes App Store Connect.
Cet article s’adresse aux développeurs indépendants qui testent ou publient une application existante avec Xcode 27, alors que le projet dépend encore d’une ancienne configuration d’écran de lancement. Il convient aussi aux petites équipes qui maintiennent plusieurs Targets, extensions ou fichiers Info.plist générés. Enfin, il sert de procédure de contrôle aux équipes qui exécutent l’Archive et l’envoi sur un Mac distant.
La condition de compilation plutôt que la version minimale
Le contrôle ne dépend pas simplement de la version minimale d’iOS déclarée par l’application. Le critère à établir est le SDK avec lequel l’App a été construite. Apple indique que les applications iPhone et iPad compilées avec le SDK iOS 27 ou une version ultérieure doivent contenir une configuration d’écran de lancement reconnue ; son absence peut provoquer ITMS-90870. La TN3208 d’Apple constitue la référence pour cette exigence.
Il faut donc séparer quatre éléments souvent confondus :
- la version minimale de déploiement inscrite dans les réglages ;
- le SDK réellement sélectionné par Xcode ;
- le fichier Info.plist présent dans le projet ;
- le fichier Info.plist inclus dans le .app envoyé.
Une application réglée pour fonctionner à partir d’une ancienne version d’iOS peut tout de même être compilée avec un SDK récent. À l’inverse, relever la version minimale de déploiement ne constitue pas, à lui seul, le déclencheur du contrôle. Cette distinction évite de modifier inutilement la compatibilité de l’application avec les anciens appareils.
Pour une chaîne de production utilisant encore le SDK iOS 26, le maintien temporaire est défendable tant que cette chaîne reste acceptée par l’environnement de publication en vigueur. En revanche, il ne faut pas attendre le jour de la sortie pour découvrir que le projet ne produit pas une Archive conforme. La branche de test Xcode 27 doit être isolée, documentée et capable de produire une Archive reproductible.
Apple a confirmé la possibilité d’envoyer des builds construites avec Xcode 27 Beta 5 vers TestFlight dans les informations de version correspondantes. Cette information ne confirme ni la date de disponibilité de la version finale de Xcode 27, ni une date précise à laquelle l’App Store acceptera tous les builds de production compilés avec le SDK iOS 27. Les deux décisions doivent rester séparées.
La déclaration de lancement et sa couverture réelle
Le serveur ne vérifie pas seulement que l’application s’ouvre sur un appareil. Il examine le paquet livré. Une configuration visuellement fonctionnelle mais absente de l’Info.plist final ne constitue donc pas une correction suffisante.
La déclaration peut prendre plusieurs formes selon l’architecture du projet. Apple documente notamment la clé UILaunchScreen et les règles de configuration dans sa documentation consacrée à l’écran de lancement. La référence de UILaunchScreen précise les propriétés que le système peut interpréter.
Un écran déclaré par UILaunchScreen
Cette approche convient lorsqu’un projet peut décrire son écran de lancement avec les propriétés prévues dans l’Info.plist. Elle limite la dépendance à un fichier storyboard séparé, mais elle exige que les noms de ressources, les images et les paramètres de compilation correspondent exactement au contenu livré.
Une clé vide, une valeur temporaire ou un nom de fichier qui n’existe pas dans le paquet ne doit pas être utilisé comme solution de contournement. Le contrôle serveur peut disparaître tandis que l’application affiche un écran incomplet, une image absente ou une mise en page incorrecte.
Un LaunchScreen.storyboard
Un projet UIKit ancien peut déjà dépendre d’un storyboard de lancement. Dans ce cas, conserver cette structure est souvent moins risqué que de reconstruire toute la configuration. Il faut cependant vérifier que le storyboard appartient au bon Target, qu’il est inclus dans les ressources de l’Archive et que le réglage de compilation pointe vers son nom réel.
Le choix ne se résume donc pas à « moderne » contre « ancien ». Nous retenons généralement UILaunchScreen lorsqu’une déclaration simple suffit et LaunchScreen.storyboard lorsqu’un projet UIKit existant possède déjà une ressource validée. Pour un projet multiplateforme, la priorité est de vérifier le fichier généré par l’outil de construction iOS, pas uniquement le fichier de configuration partagé.
Attention. Un fichier Info.plist visible dans le navigateur du projet peut ne pas être celui qui arrive dans l’Archive. Les réglages de compilation et les scripts peuvent générer, fusionner ou remplacer des valeurs pendant la construction. La cible livrée doit toujours être l’objet de la vérification.
Les Targets et configurations qui passent entre les mailles
Dans un projet SwiftUI, Xcode peut générer automatiquement une partie de l’Info.plist. Cela ne signifie pas que chaque App Target possède automatiquement la déclaration attendue. Une application peut avoir une cible principale, une cible de prévisualisation, une extension de partage et une configuration de distribution qui ne consomment pas les mêmes paramètres.
Dans un projet UIKit, le fichier plist est souvent maintenu manuellement. Le risque est différent : la déclaration existe, mais elle n’est attachée qu’à Debug, à un ancien Target ou à une ressource exclue de Release.
Les projets générés par Flutter, React Native ou un autre framework ajoutent une couche supplémentaire. Le fichier source peut être modifié avant chaque construction. Un script peut aussi injecter des valeurs selon la configuration choisie. Dans ce contexte, corriger le plist à la main puis lancer une commande d’automatisation sans contrôler sa sortie ne suffit pas.
Nous procédons Target par Target :
- Identifier le Bundle ID de l’application réellement envoyée.
- Repérer le schéma utilisé pour l’Archive.
- Vérifier la configuration de build associée à ce schéma.
- Comparer le fichier Info.plist source avec les réglages qui peuvent le générer.
- Contrôler les scripts exécutés avant et après la compilation.
- Vérifier que le storyboard ou les ressources de lancement appartiennent à la cible distribuée.
- Reproduire la même vérification pour les variantes régionales ou les éditions payantes, si elles produisent des paquets distincts.
Cette méthode évite une erreur fréquente : corriger le projet principal alors que l’Archive provient d’un autre schéma. Elle est également utile lorsque l’extension est conforme mais que l’application conteneur ne l’est pas.
L’Archive Release comme mesure de conformité
La source du projet est une intention. L’Archive est la preuve de ce qui sera envoyé. Pour ITMS-90870, la mesure décisive se trouve donc dans le .app inclus dans l’Archive Release.
Procédure de contrôle reproductible
Nous recommandons la séquence suivante, sans supprimer par défaut les données de compilation ni réinstaller Xcode :
- Noter l’environnement. Relevez la version de Xcode, le SDK sélectionné, le schéma, la configuration et l’identifiant de la cible.
- Nettoyer la configuration du projet. Retirez les clés de lancement vides, les références obsolètes et les fichiers qui ne sont plus présents.
- Construire en Release. Lancez l’Archive depuis le même schéma que celui utilisé pour l’envoi, et non depuis une exécution Debug.
- Ouvrir le paquet produit. Dans l’Archive, localisez le fichier
.app, puis examinez sonInfo.plistfinal. - Contrôler les ressources. Vérifiez la présence du storyboard ou des fichiers déclarés, leurs noms exacts et leur inclusion dans le paquet.
- Comparer les réglages. Conservez une copie expurgée des paramètres pertinents et comparez-la avec la sortie de la construction automatisée.
- Exporter ou distribuer. Utilisez l’entrée d’Archive habituelle afin de ne pas valider un chemin différent de celui de la production.
- Envoyer à TestFlight. Une nouvelle build doit être traitée par App Store Connect avant toute décision de publication.
- Archiver les preuves. Conservez le numéro de build, le journal d’envoi, la version de Xcode et le résultat du contrôle de l’Info.plist.
La référence Apple des réglages de compilation aide à retrouver les paramètres susceptibles de modifier le produit final. Pour l’envoi, utilisez la procédure officielle de téléversement des builds dans App Store Connect, puis consultez le statut de la build plutôt que de considérer la fin de la commande comme une validation.
Cette distinction est essentielle dans une chaîne distante. Un terminal peut signaler que l’export s’est terminé alors que le serveur reçoit une Archive construite avec un autre schéma, un autre fichier plist ou une autre version de Xcode.
Le premier affichage après installation
La validation serveur ne remplace pas le contrôle utilisateur. Après avoir installé la nouvelle build, supprimez l’ancienne application avant de la relancer. Apple recommande cette approche pour éviter qu’un écran conservé par le système ne donne une fausse impression de correction ; reportez-vous aux indications de la TN3208.
Vérifiez ensuite :
- l’absence d’écran blanc ;
- l’absence d’une ancienne image de lancement ;
- le cadrage sur les formats d’iPhone et d’iPad visés ;
- la présence correcte des zones sûres ;
- le rendu en mode clair et sombre si le design le prévoit ;
- la cohérence entre l’application fraîchement installée et celle mise à jour.
Le simulateur accélère la vérification des variantes visuelles. Il ne remplace pas un appareil réel avant la publication, en particulier pour une interface graphique, une application audio ou vidéo et un produit dont l’écran de lancement doit respecter une direction artistique précise. Nous ne transformons pas une impression de vitesse d’affichage en mesure de performance sans test identifié.
La validation dans un Mac distant
Un Mac distant ne doit pas être considéré comme une simple machine qui exécute une commande SSH. Il devient une partie de la chaîne de livraison. L’environnement doit reprendre la version de Xcode prévue, le schéma, la configuration Release, les certificats nécessaires et le même point d’entrée d’Archive.
Cette vérification est particulièrement importante lorsque le projet SwiftUI s’appuie sur une génération automatique ou lorsqu’un script multiplateforme prépare l’Info.plist. Une différence d’environnement peut modifier le fichier généré sans toucher au dépôt source.
La séquence de validation que nous appliquons est la suivante :
- ouvrir une session interactive et confirmer la version de Xcode ;
- vérifier le SDK et le schéma avant de lancer l’Archive ;
- produire une Archive dans l’interface de Xcode ;
- produire une Archive par le script approuvé ;
- comparer le Bundle ID, la configuration de lancement et les ressources du .app ;
- envoyer la sortie retenue à TestFlight ;
- consigner le résultat et le point de retour vers la chaîne utilisant le SDK iOS 26.
Si l’environnement local ne peut pas installer la version nécessaire, un Mac distant pour les outils de développement Apple peut servir de poste de validation indépendant. L’objectif n’est pas de remplacer immédiatement la machine de production, mais de vérifier une branche Xcode 27 avant de modifier la chaîne stable.
Tableau de décision de la configuration
| Situation observée | Choix de configuration | Contrôle obligatoire |
|---|---|---|
| Projet UIKit déjà livré avec un storyboard de lancement fonctionnel | Conserver LaunchScreen.storyboard |
Vérifier le Target, le nom de ressource et le contenu du .app |
| Projet SwiftUI avec génération automatique | Utiliser la déclaration générée ou compléter UILaunchScreen |
Inspecter l’Info.plist final de l’Archive |
| Projet multiplateforme avec plist réécrit par script | Corriger la source de génération | Rejouer le script en configuration Release |
| Plusieurs Targets ou éditions de l’application | Traiter chaque App Target séparément | Comparer chaque Bundle ID et chaque Archive |
| Déclaration présente mais fichier absent | Remplacer la référence invalide | Vérifier les ressources copiées dans le paquet |
La checklist d’acceptation avant l’envoi
Cochez chaque élément dans l’ordre. Une case non vérifiable doit bloquer l’envoi, plutôt que d’être remplacée par une supposition.
- [ ] Le SDK de l’Archive a été identifié et correspond à la branche testée.
- [ ] La version minimale de déploiement n’a pas été confondue avec le SDK de compilation.
- [ ] Le Target envoyé possède une configuration de lancement reconnue.
- [ ] Les clés vides et les références de fichiers inexistants ont été supprimées.
- [ ] Le choix entre
UILaunchScreenetLaunchScreen.storyboardest documenté. - [ ] Le storyboard ou les ressources appartiennent bien au Target Release.
- [ ] Les configurations Debug et Release ont été comparées.
- [ ] Les scripts de génération ou de modification de l’Info.plist ont été inspectés.
- [ ] Une Archive Release a été créée avec le schéma de production.
- [ ] L’Info.plist du
.appcontenu dans l’Archive a été ouvert. - [ ] Les ressources de lancement sont présentes dans ce même
.app. - [ ] Une installation propre a été testée sur le simulateur.
- [ ] Un appareil réel a été utilisé avant la publication.
- [ ] Une build a été envoyée à TestFlight.
- [ ] Le journal d’envoi et le statut App Store Connect ont été conservés.
- [ ] Le retour vers la chaîne utilisant le SDK iOS 26 est encore possible.
Tableau de séparation des preuves
| Élément contrôlé | Ce qu’il prouve | Ce qu’il ne prouve pas |
|---|---|---|
| Réglage du projet | L’intention de configuration du développeur | Que le réglage est présent dans l’Archive |
| Info.plist source | La déclaration enregistrée dans le dépôt | Qu’un script ne la remplacera pas |
Info.plist du .app |
Le contenu réellement préparé pour l’envoi | Que l’écran s’affiche correctement sur chaque appareil |
| Ressources du paquet | La présence des fichiers nécessaires | Leur rendu visuel dans toutes les orientations |
| TestFlight accepté | La disparition du blocage serveur pour cette build | L’acceptation définitive d’une prochaine build de production |
| Test sur appareil réel | Le comportement visible après installation propre | La conformité d’une autre cible ou d’un autre schéma |
FAQ de dépannage
ITMS-90870 « Missing launch screen »
Si l’erreur apparaît, commencez par vérifier que l’Archive utilise le SDK iOS 27 ou une version ultérieure. Ajoutez ensuite une déclaration Apple reconnue, puis contrôlez le fichier Info.plist du .app, et non seulement celui du projet. Une nouvelle Archive Release est nécessaire. L’envoi à TestFlight sert ensuite à vérifier que le serveur ne reproduit plus ITMS-90870.
Projet SwiftUI et Info.plist généré
La génération automatique peut fonctionner pour un Target et manquer pour un autre. Elle peut également être modifiée par la configuration Release ou par un script du framework. Ouvrez l’Archive produite, relevez la déclaration finale et comparez-la avec la sortie de la commande automatisée. Cette méthode répond au problème sans supposer que l’interface Xcode reflète toujours le paquet livré.
UILaunchScreen ou LaunchScreen.storyboard
Nous choisissons UILaunchScreen lorsqu’une déclaration par propriétés suffit et que les ressources sont simples à maintenir. Nous conservons LaunchScreen.storyboard dans un projet UIKit ancien lorsqu’il est déjà rattaché au bon Target. Dans les deux cas, la conformité dépend du contenu final du paquet. Une clé reconnue mais mal renseignée ne garantit pas un affichage acceptable.
Contrôle d’une Archive
L’Archive doit être produite en Release avec le schéma d’envoi. Localisez ensuite le .app, examinez son Info.plist et vérifiez les ressources qu’il contient. Comparez ces éléments avec le résultat du script automatisé. Cette inspection est plus fiable qu’un contrôle du seul fichier source, car les réglages de compilation peuvent modifier ou remplacer la configuration pendant la construction.
Xcode 27 Beta et distribution
Xcode 27 Beta 5 est confirmé comme compatible avec l’envoi de builds à TestFlight selon les notes Apple disponibles. Il ne faut pas en déduire une autorisation générale pour la publication commerciale dans l’App Store. Avant de basculer une chaîne de production, vérifiez la version de Xcode, les notes App Store Connect et la politique d’acceptation alors en vigueur.
Choisir entre la chaîne actuelle et un Mac de validation
Conserver la chaîne compilée avec le SDK iOS 26 limite le risque immédiat, mais elle laisse le projet sans preuve de conformité pour le SDK iOS 27. Utiliser uniquement un poste local ancien complique aussi l’installation parallèle de Xcode, augmente les risques de modifier l’environnement de production et rend plus difficile la reproduction d’un échec propre à l’Archive.
Une machine partagée ou une configuration distante improvisée ajoute d’autres défauts : certificats difficiles à isoler, scripts lancés avec le mauvais schéma et absence de journal centralisé. Pour une validation ponctuelle, l’achat d’un Mac supplémentaire immobilise en revanche un budget et du matériel qui peuvent rester inutilisés entre deux versions.
Dans ce cas précis, la solution la plus équilibrée consiste à conserver la chaîne stable, puis à utiliser une instance macOS indépendante pour tester Xcode 27, produire l’Archive et effectuer l’envoi TestFlight. Si votre ordinateur ne peut pas installer l’outil requis, louer un Mac à distance avec MESHLAUNCH permet de réaliser cette validation sans remplacer immédiatement le poste de production. Pour un besoin permanent, une machine achetée reste plus cohérente si la charge est continue ou si des périphériques physiques sont indispensables.
La règle opérationnelle est simple : ne déclarez pas la correction terminée lorsque le projet compile. Déclarez-la terminée lorsque le Target correct produit une Archive conforme, que l’écran s’affiche après une installation propre et que TestFlight accepte la nouvelle build sans ITMS-90870.