← Todos os Posts

A regra da launch screen no iOS 27: quatro chaves ou rejeição

As notas de versão do iOS 27 da Apple transformam uma frase da documentação em uma barreira de envio: “Apps de iOS e iPadOS compilados com o SDK 27.0 ou posterior precisam incluir uma launch screen. O Info.plist do seu app deve conter uma das seguintes chaves: UILaunchStoryboardName, UILaunchStoryboards, UILaunchScreen ou UILaunchScreens. Apps que não incluem uma launch screen são rejeitados quando a App Store começar a aceitar apps compilados com o SDK 27.0.”1

A exigência em si é antiga. O guia do Xcode da Apple abre com “todo app de iOS precisa fornecer uma launch screen.”2 O que chega no iOS 27 é a consequência de ignorá-la.

Resumo

  • Apps compilados com o SDK 27.0 do iOS ou posterior precisam declarar uma launch screen por meio de uma das quatro chaves do Info.plist, e a App Store rejeita as builds que não fazem isso.1
  • A barreira está no envio, não na execução. A Apple escreve “rejeitados quando a App Store começar a aceitar apps compilados com o SDK 27.0”, ou seja, a falha acontece no App Store Connect, e não no aparelho do usuário.1
  • A regra cita iOS e iPadOS e para por aí. A Apple não a estende a tvOS, visionOS ou Mac Catalyst na mesma nota.1 Já a exigência do ciclo de vida baseado em cenas, que chega no mesmo ciclo, tem outra leitura: o guia de migração dela cita nominalmente iOS 27, iPadOS 27, Mac Catalyst 27, tvOS 27 e visionOS 27.3
  • Duas chaves cobrem uma única launch screen (UILaunchScreen monta a tela dentro da property list, UILaunchStoryboardName aponta para um arquivo de storyboard) e duas cobrem variantes por esquema de URL (UILaunchScreens, UILaunchStoryboards). Três das quatro são dicionários; só UILaunchStoryboardName é uma string.4567
  • Projetos criados a partir de templates recentes do Xcode já cumprem a regra — e cumprem por meio de uma configuração de build, não de um arquivo.811 Auditar o repositório com grep pelas quatro chaves, portanto, não encontra a resposta de jeito nenhum.

A regra, dita com precisão

Três detalhes da frase da Apple têm peso, e a cobertura do assunto costuma embaralhar os três.

Primeiro, o gatilho é o SDK com o qual você compila, não o sistema que seus usuários rodam. Um binário compilado com o iOS 26 mantém seu lugar na loja. Recompile com o Xcode 27 para aproveitar qualquer coisa do novo SDK e a exigência vem junto.

Segundo, o ponto de aplicação é a aceitação na App Store. A Apple escreveu “rejeitados”, o que coloca a falha na revisão do envio, e não na inicialização. Essa distinção separa a regra da launch screen da exigência do ciclo de vida baseado em cenas, que chega no mesmo ciclo e onde a redação da Apple é que os apps “não conseguem iniciar”.1 Uma custa uma build rejeitada; a outra custa um app morto no celular do usuário.

Terceiro, o escopo é iOS e iPadOS. A nota da Apple nomeia essas duas plataformas e para. Quem mantém um target Catalyst ou tvOS deve ler a exigência como não declarada, e não como estendida por analogia. O ciclo 27 aperta bastante em outros pontos — do ciclo de vida baseado em cenas em cinco plataformas até a remoção do ImageCreator do Image Playground —, mas a nota da launch screen continua restrita.

Qual das quatro chaves se aplica

A Apple oferece duas formas de construir uma launch screen e duas cardinalidades, o que produz as quatro chaves.

UILaunchScreen configura a interface de inicialização diretamente na property list, sem nenhum arquivo de storyboard envolvido. A Apple a descreve como a forma de “configurar a interface do usuário durante a inicialização do app sem depender de storyboards”, e ela aceita chaves filhas para a cor de fundo, a imagem e a visibilidade da barra de navegação, da tab bar e da barra de ferramentas.4 Para um app cuja primeira tela é um fundo liso, um dicionário UILaunchScreen vazio já satisfaz a regra. O próprio sistema de build do Xcode segue esse caminho: “quando GENERATE_INFOPLIST_FILE está habilitado”, INFOPLIST_KEY_UILaunchScreen_Generation “define o valor da chave UILaunchScreen no arquivo Info.plist como um dicionário vazio”.8

UILaunchStoryboardName aponta para um storyboard pelo nome do arquivo, sem a extensão: um arquivo LaunchScreen.storyboard vira a string LaunchScreen.5 Ela existe desde o iOS 9 e é a única das quatro que recebe uma string em vez de um dicionário.5 Apps com um estado de inicialização desenhado — ou qualquer projeto que inclua o LaunchScreen.storyboard que o Xcode ainda adiciona aos seus templates de storyboard — querem essa chave.2

As formas no plural existem para um caso específico, e ambas são dicionários, não arrays.67 UILaunchScreens contém três chaves filhas: UILaunchScreenDefinitions, o array de configurações de launch screen, cada uma com um UILaunchScreenIdentifier; UIURLToLaunchScreenAssociations, o mapa de esquema de URL para identificador; e UIDefaultLaunchScreen, o fallback.6 UILaunchStoryboards espelha esse formato com UILaunchStoryboardDefinitions, UIURLToLaunchStoryboardAssociations e UIDefaultLaunchStoryboard.7 Qualquer uma das duas permite que um app aberto a partir de myapp://compose apresente um estado de inicialização diferente do mesmo app aberto pela tela de início. A Apple é direta ao dizer que a maioria dos apps deve ignorá-las: “se você precisa de apenas uma launch screen, use UILaunchScreen.”6

A decisão prática se resume a uma pergunta. Se sua launch screen é um storyboard, declare UILaunchStoryboardName. Se não é, declare UILaunchScreen. Recorra a uma chave no plural só quando você já souber por que precisa dela.

Os apps que realmente são pegos

Um app criado a partir de um template atual do Xcode passa sem que ninguém encoste nele, e é exatamente por isso que a regra é fácil de descartar — e fácil de tropeçar nela. A população em risco tem um traço em comum: ninguém no time escreveu o Info.plist à mão recentemente.

Property lists geradas são a maior categoria, e o próprio Xcode é o maior gerador. O Xcode 13 mudou o padrão: projetos criados a partir de vários templates “não exigem mais arquivos de configuração como entitlements e arquivos Info.plist”, e você configura os campos na aba Info do target e no editor de build settings.9 Toolchains multiplataforma, frameworks wrapper e scripts de build que sintetizam um plist na hora do empacotamento acrescentam uma segunda camada, e seus templates podem ser anteriores ao próprio UILaunchScreen. Ninguém revisa um arquivo que o sistema de build escreve.

Plists esvaziados são a segunda categoria. Launch storyboards são apagados durante uma otimização de tamanho, durante uma migração para fora do Interface Builder, ou numa limpeza que removeu o último storyboard do projeto e levou a launch screen junto. O app continuou compilando, então a remoção pareceu segura.

Projetos herdados são a terceira, e esse grupo é mais restrito do que boa parte da cobertura supõe. UILaunchStoryboardName chegou no iOS 9, então um projeto que vem sendo mantido desde 2015 já tem uma chave que qualifica.5 Os apps que não têm nenhuma das quatro são mais antigos que isso: aqueles que ainda declaram a arte de inicialização por UILaunchImages, a chave do iOS 7.0 que a Apple depreciou no iOS 13.0 com uma única instrução, “UILaunchImages foi depreciada; use launch storyboards do Xcode.”10 Um array UILaunchImages não está na lista de quatro da Apple, então um projeto que ainda depende dele e nunca adotou uma referência de storyboard não tem nada que a exigência aceite. Uma década de atualizações do Xcode não terá acrescentado nenhuma, porque nada na compilação jamais falhou.

Auditar um Info.plist que o sistema de build escreve

Comece aceitando que o arquivo pode não existir. GENERATE_INFOPLIST_FILE liga a geração automática, e cada build setting INFOPLIST_KEY_* grava uma chave no plist que a build produz.8 As launch screens têm duas dessas configurações: INFOPLIST_KEY_UILaunchScreen_Generation, que grava um dicionário UILaunchScreen vazio, e INFOPLIST_KEY_UILaunchStoryboardName, que grava o nome do storyboard.8 Nenhuma das duas deixa qualquer coisa para uma busca textual encontrar. O template atual de app SwiftUI para iOS do Xcode traz INFOPLIST_KEY_UILaunchScreen_Generation = YES nas configurações compartilhadas, então um projeto criado assim tem um target em conformidade sem nenhum texto de launch screen em lugar algum do repositório.11

Pergunte ao sistema de build, não ao sistema de arquivos:

xcodebuild -showBuildSettings \
  -project YourApp.xcodeproj -target YourApp \
  -configuration Release -sdk iphoneos 2>/dev/null \
  | grep -E "^ +(GENERATE_INFOPLIST_FILE|INFOPLIST_FILE|INFOPLIST_KEY_UILaunch)"

Rodando contra o projeto Ace Citizenship na minha máquina, voltam três linhas:11

    GENERATE_INFOPLIST_FILE = YES
    INFOPLIST_FILE = Ace-Citizenship-Info.plist
    INFOPLIST_KEY_UILaunchScreen_Generation = YES

A terceira linha é toda a resposta sobre conformidade, e nenhum arquivo do repositório a contém. Leia a saída nessa ordem. GENERATE_INFOPLIST_FILE = YES mais uma linha INFOPLIST_KEY_UILaunch definida como YES significa que o sistema de build grava a chave por você: a Apple condiciona toda configuração INFOPLIST_KEY_* à geração estar habilitada, então a mesma linha é inerte sob GENERATE_INFOPLIST_FILE = NO, e um valor NO não grava nada de qualquer forma.8 Com a geração desligada, um caminho em INFOPLIST_FILE é onde sua chave de launch screen precisa estar; então abra esse arquivo e procure uma das quatro. Com a geração ligada e um caminho de arquivo presente, o sistema de build mescla os dois e qualquer uma das fontes satisfaz a exigência.8

As duas flags merecem seu lugar. -configuration Release importa porque a revisão da App Store vê o produto Release. -sdk iphoneos importa porque o Xcode grava essas configurações por SDK em targets multiplataforma: o projeto Reps declara INFOPLIST_KEY_UILaunchScreen_Generation três vezes, uma para cada um de [sdk=iphoneos*], [sdk=iphonesimulator*] e [sdk=appletv*], e o Banana List declara as duas primeiras. Tire o -sdk iphoneos e nenhuma delas é resolvida, então a chave some da saída e um target em conformidade parece exposto.11

Depois, verifique o artefato que você realmente envia. Na saída de plutil -p, dois espaços à esquerda marcam uma chave de nível superior:

plutil -p YourApp.xcarchive/Products/Applications/*.app/Info.plist \
  | grep -E '^  "UILaunch'

Contra um archive do Return compilado para distribuição em abril, volta uma linha; o mesmo comando contra um bundle sem launch screen não imprime nada e sai com código 1:11

  "UILaunchScreen" => {

Aqui, recorra a plutil em vez de PlistBuddy. Diante de um caminho que não resolve, PlistBuddy -c "Print" escreve “File Doesn’t Exist, Will Create:” e um Dict { } vazio na saída padrão e sai com código 0; jogue isso num grep pelas chaves de launch screen e a única linha que revelaria o erro é engolida, deixando uma saída vazia que parece exatamente uma chave ausente. O plutil nomeia o arquivo que não conseguiu abrir e sai com código 1.11

Uma varredura do repositório ainda tem função, mas menor do que parece: encontrar plists mantidos à mão que valem a leitura.

find . -name "Info.plist" \
  -not -path "*/build/*" -not -path "*/DerivedData/*" \
  -not -path "*/.build/*" -not -path "*/Carthage/*" -not -path "*/Pods/*" \
  -print0 | xargs -0 grep -L -E "UILaunchScreen|UILaunchStoryboard"

Todo caminho que ela imprime é um candidato a conferir nas build settings, não um target que vai falhar no envio. No Banana List o comando retorna exatamente uma linha, ./Banana List/Info.plist, e esse target entrega uma launch screen mesmo assim: suas build settings carregam INFOPLIST_KEY_UILaunchScreen_Generation, e o bundle arquivado contém UILaunchScreen. Sem as exclusões, o mesmo comando retorna 25 linhas nesse repositório, 24 delas artefatos de build dentro de build/, incluindo bundles de test runner, XCTest.framework, um log .xcresult e um app de watch.11

Acrescentar a chave à mão exige alguns passos, não uma edição de texto. A sequência da Apple: nas configurações do seu target, selecione a aba Info; na seção Custom iOS Target Properties, expanda a chave Launch Screen; clique no botão Add, digite UILaunchScreen e pressione Return; depois selecione a chave UILaunchScreen, clique em Add de novo e adicione chaves filhas para as opções de aparência que você quiser.2 Num plist gerado pelo Xcode, definir INFOPLIST_KEY_UILaunchScreen_Generation como YES nas build settings do target faz o mesmo serviço e sobrevive à próxima build.8 Para um plist gerado por outra coisa que não o Xcode, corrija o template do gerador; a próxima build descarta qualquer edição feita na saída.

O que a regra não diz

A Apple não publicou uma data. O gatilho é formulado como “quando a App Store começar a aceitar apps compilados com o SDK 27.0”, algo que historicamente acontece perto do lançamento do sistema no outono do hemisfério norte, mas que a Apple não colocou por escrito neste ciclo.1 Trate qualquer data específica que você ler como inferência.

A Apple também não disse que apps existentes param de funcionar, que builds do TestFlight são afetadas, nem que a exigência vai além de iOS e iPadOS. A nota cobre o envio de novas builds e nada mais.

A correção é pequena o bastante para que a pergunta interessante não seja como cumprir, e sim se você já cumpre. Para um projeto mantido à mão, a resposta é quase certamente sim. Para qualquer coisa com plist gerado, vale confirmar com o sistema de build antes de a loja começar a dizer não.

Perguntas frequentes

Um app criado a partir de um template atual do Xcode já está em conformidade?

Quase certamente, e a evidência está nas build settings, não em um arquivo. O template de app SwiftUI para iOS do Xcode define INFOPLIST_KEY_UILaunchScreen_Generation = YES nas configurações compartilhadas, o que grava um dicionário UILaunchScreen vazio no Info.plist que o sistema de build produz.811 Confirme rodando xcodebuild -showBuildSettings para a configuração Release com -sdk iphoneos e procurando por uma linha INFOPLIST_KEY_UILaunch.

Por que o grep de UILaunchScreen no meu repositório não encontra nada?

Porque, desde o Xcode 13, projetos criados a partir de vários templates não têm nenhum Info.plist em disco; a Apple moveu esses campos para a aba Info do target e para o editor de build settings.9 A launch screen chega por INFOPLIST_KEY_UILaunchScreen_Generation ou INFOPLIST_KEY_UILaunchStoryboardName no momento da build.8 Uma busca textual pelos arquivos-fonte não enxerga nenhuma das duas configurações, e os arquivos Info.plist que ela encontra costumam ser fragmentos parciais que o sistema de build mescla, ou artefatos de build dentro de build/ e DerivedData/.

Qual chave devo adicionar se realmente não tenho nenhuma?

UILaunchStoryboardName se você entrega um LaunchScreen.storyboard, e UILaunchScreen se não entrega.45 Um dicionário UILaunchScreen vazio basta para um app que inicia com um fundo liso, que é o que o Xcode gera por padrão.8 Ignore UILaunchScreens e UILaunchStoryboards a menos que você apresente estados de inicialização diferentes para esquemas de URL diferentes; a própria orientação da Apple é “se você precisa de apenas uma launch screen, use UILaunchScreen.”6

A exigência vale para builds do TestFlight?

A nota da Apple não diz. Ela cita uma única consequência, a rejeição “quando a App Store começar a aceitar apps compilados com o SDK 27.0”, e a distribuição via TestFlight não aparece em lugar nenhum ali.1 Como builds do TestFlight passam pelo App Store Connect e pela revisão de beta, a suposição segura é que uma build que não cumpre a exigência falha em todo lugar onde encontra revisão — mas a Apple não escreveu isso. Quem depende dessa resposta deveria testar um upload feito com o SDK 27.0 em vez de confiar em qualquer leitura do silêncio.

Pontos principais

Para desenvolvedores iOS: - Consulte as build settings antes de rodar grep nos arquivos. Rode xcodebuild -showBuildSettings -configuration Release -sdk iphoneos e procure por INFOPLIST_KEY_UILaunchScreen_Generation ou INFOPLIST_KEY_UILaunchStoryboardName.8 Uma busca textual no repositório não enxerga nenhuma das duas. - Escolha UILaunchStoryboardName se você entrega um launch storyboard e UILaunchScreen se não entrega. Ignore as chaves no plural, a menos que você sirva estados de inicialização diferentes por esquema de URL.

Para times que publicam via toolchains multiplataforma: - Audite o bundle .app arquivado com plutil -p, não o arquivo no controle de versão. A saída do gerador é o que a revisão vê, e o plutil falha de forma explícita diante de um caminho inválido, enquanto o PlistBuddy imprime um dicionário vazio e sai com código 0. - Corrija o template do plist na sua configuração de build, e não o arquivo gerado, ou a próxima build descarta a correção.

Para gerentes de release: - A falha aparece no envio à App Store, não em tempo de execução, então custa um ciclo de revisão em vez de um incidente em produção. Agende a auditoria antes do primeiro envio feito com o SDK 27.0, não depois de uma rejeição. - Combine a verificação com a migração para o ciclo de vida baseado em cenas, que compartilha o mesmo gatilho e traz uma penalidade mais dura.


O ciclo 27 segue convertendo sugestões em imposições: o ImageCreator para de funcionar, o ciclo de vida baseado em cenas vira requisito de inicialização e a launch screen vira barreira de envio. Para o resto do que chega no mesmo SDK, veja Novidades do SwiftUI no iOS 27. O hub completo da série é a Série Ecossistema Apple.

Referências


  1. Apple, iOS & iPadOS 27 Release Notes, seção UIKit. Fonte da exigência da launch screen, em New Features (radar 168247372): “iOS and iPadOS apps built with the 27.0 SDK or later are required to include a launch screen. Your app’s Info.plist must contain one of the following keys: UILaunchStoryboardName, UILaunchStoryboards, UILaunchScreen, or UILaunchScreens. Apps that don’t include a launch screen are rejected when the App Store begins accepting apps built with the 27.0 SDK.” Também é a fonte da redação sobre o ciclo de vida baseado em cenas citada aqui, que aparece separadamente em Deprecations (radar 141837548): “Apps built with the latest SDK must adopt the scene-based life cycle or they fail to launch.” Essa entrada não traz lista de plataformas. Verificado no JSON da documentação da Apple em 25 de julho de 2026. 

  2. Apple, Specifying your app’s launch screen, documentação do Xcode. Fonte de “Every iOS app must provide a launch screen”, dos dois métodos suportados (information property list e arquivo de interface de usuário) e dos passos de property list citados aqui: selecionar a aba Info nas configurações do seu target, expandir a chave Launch Screen na seção Custom iOS Target Properties, adicionar a chave UILaunchScreen e então adicionar chaves filhas para as opções de configuração. 

  3. Apple, Transitioning to the UIKit scene-based life cycle, Apple Developer Documentation. Fonte da enumeração das cinco plataformas: “Beginning in iOS 27, iPadOS 27, Mac Catalyst 27, tvOS 27, and visionOS 27, apps built with the latest SDK must adopt the scene-based life cycle or they fail to launch.” 

  4. Apple, UILaunchScreen, referência da Information Property List. Dicionário, iOS e iPadOS 14.0 e posteriores. Fonte de “to configure the user interface during app launch in a way that doesn’t rely on storyboards” e das chaves filhas (UIColorName, UIImageName, UIImageRespectsSafeAreaInsets, UINavigationBar, UITabBar, UIToolbar). 

  5. Apple, UILaunchStoryboardName, referência da Information Property List. String, iOS e iPadOS 9.0 e posteriores (também tvOS 9.0, watchOS 2.0). Fonte da regra do nome de arquivo sem extensão. 

  6. Apple, UILaunchScreens, referência da Information Property List. Dicionário, iOS e iPadOS 14.0 e posteriores. Fonte das chaves filhas UILaunchScreenDefinitions (o array de configurações, cada uma com um UILaunchScreenIdentifier), UIURLToLaunchScreenAssociations e UIDefaultLaunchScreen, e de “If you need only one launch screen, use UILaunchScreen instead.” 

  7. Apple, UILaunchStoryboards, referência da Information Property List. Dicionário, iOS e iPadOS 9.0 e posteriores. Fonte das chaves filhas UILaunchStoryboardDefinitions, UIDefaultLaunchStoryboard e UIURLToLaunchStoryboardAssociations, e do redirecionamento para UILaunchStoryboardName no caso de um único launch storyboard. 

  8. Apple, Build settings reference, documentação do Xcode. Fonte de GENERATE_INFOPLIST_FILE (“Automatically generate an Info.plist file”), INFOPLIST_FILE (o sistema de build “merges the values you specify in this file with other values it generates during the build process” e “When GENERATE_INFOPLIST_FILE is enabled, the build system also includes content from build settings in the merge process”), INFOPLIST_KEY_UILaunchScreen_Generation (“sets the value of the UILaunchScreen key in the Info.plist file to an empty dictionary”) e INFOPLIST_KEY_UILaunchStoryboardName

  9. Apple, Xcode 13 Release Notes, Templates, Resolved Issues (radar 68254857): “Projects created from several templates no longer require configuration files such as entitlements and Info.plist files. Configure common fields in the target’s Info tab, and build settings in the project editor. These files are added to the project when additional fields are used.” 

  10. Apple, UILaunchImages, referência da Information Property List. Array de dicionários, introduzido no iOS 7.0 e depreciado no iOS 13.0. Fonte de “UILaunchImages has been deprecated; use Xcode launch storyboards instead.” 

  11. Testes do autor no macOS 26.5.2 com Xcode 26.6 (build 17F113), 25 de julho de 2026, contra quatro projetos iOS em produção: Ace Citizenship, Banana List, Reps e Return. Saída dos comandos reproduzida na íntegra. O comportamento do PlistBuddy foi confirmado diretamente: /usr/libexec/PlistBuddy -c "Print" /nonexistent/Info.plist imprime “File Doesn’t Exist, Will Create:” seguido de Dict { } e sai com código 0, enquanto plutil -p no mesmo caminho imprime “The file “Info.plist” couldn’t be opened because there is no such file” e sai com código 1. A configuração do template vem de iOS SwiftUI App.xctemplate/TemplateInfo.plist na toolchain do Xcode instalada. 

Artigos relacionados

A obrigatoriedade de scenes do UIKit: o que não inicia no iOS 27

Apps compilados com o SDK do iOS 27 precisam adotar o ciclo de vida de scenes do UIKit ou não iniciam. O cronograma, os …

9 min de leitura

canOpenURL foi descontinuado: o que chamar no lugar

A Apple descontinuou o canOpenURL e cortou o teto de esquemas permitidos para 25. Veja o substituto e o que ele não faz.

26 min de leitura