No Objective-C, podemos saber se um aplicativo está sendo criado para dispositivo ou simulador usando macros:
#if TARGET_IPHONE_SIMULATOR
// Simulator
#else
// Device
#endif
Essas são macros de tempo de compilação e não estão disponíveis no tempo de execução.
Como posso conseguir o mesmo no Swift?
Respostas:
Atualização 30/01/19
Embora essa resposta possa funcionar, a solução recomendada para uma verificação estática (conforme esclarecido por vários engenheiros da Apple) é definir um sinalizador de compilador personalizado direcionado aos simuladores do iOS. Para instruções detalhadas sobre como fazer isso, consulte a resposta de @ mbelsky .
Resposta original
Se você precisar de uma verificação estática (por exemplo, não um tempo de execução, se / else), não poderá detectar o simulador diretamente, mas poderá detectar o iOS em uma arquitetura de desktop, como segue
Após a versão Swift 4.1
Para mais esclarecimentos, você pode verificar a proposta Swift SE-0190
Claramente, isso é falso em um dispositivo, mas retorna verdadeiro para o iOS Simulator, conforme especificado na documentação :
Se você estiver desenvolvendo para um simulador que não seja o iOS, basta alterar o
os
parâmetro: por exemploDetectar o simulador watchOS
Detectar o simulador de tvOS
Ou, até, detectar qualquer simulador
Se você estiver bem com uma verificação de tempo de execução, poderá inspecionar a
TARGET_OS_SIMULATOR
variável (ouTARGET_IPHONE_SIMULATOR
no iOS 8 e abaixo), que é verdadeira em um simulador.Observe que isso é diferente e um pouco mais limitado do que usar um sinalizador de pré-processador. Por exemplo, você não poderá usá-lo no lugar onde a
if/else
é sintaticamente inválido (por exemplo, fora do escopo das funções).Digamos, por exemplo, que você deseja ter importações diferentes no dispositivo e no simulador. Isso é impossível com uma verificação dinâmica, enquanto que é trivial com uma verificação estática.
Além disso, como o sinalizador é substituído por a
0
ou a1
pelo pré-processador rápido, se você o usar diretamente em umaif/else
expressão, o compilador emitirá um aviso sobre código inacessível.Para contornar esse aviso, consulte uma das outras respostas.
fonte
arch(i386) && os(iOS)
.#if targetEnvironment(simulator)
:) ( github.com/apple/swift-evolution/blob/master/proposals/… )ATUALIZADO PARA SWIFT 4.1. Use em
#if targetEnvironment(simulator)
vez disso. FontePara detectar o simulador no Swift, você pode usar a configuração de compilação:
Agora você pode usar esta declaração para detectar o simulador:
Além disso, você pode estender a classe UIDevice:
fonte
xcconfig
arquivos usandoOTHER_SWIFT_FLAGS = TARGET_OS_EMBEDDED
eOTHER_SWIFT_FLAGS[sdk=embeddedsimulator*] = TARGET_OS_SIMULATOR
para substituir o Simulador.Informações atualizadas a partir de 20 de fevereiro de 2018
Parece que @russbishop tem uma resposta autorizada que a torna "incorreta" - mesmo que pareça funcionar por um longo tempo.
Detectar se o aplicativo está sendo criado para o dispositivo ou simulador no Swift
Resposta Anterior
Com base na resposta do @ WZW e nos comentários do @ Pang, criei uma estrutura de utilitário simples. Esta solução evita os avisos produzidos pela resposta da @ WZW.
Exemplo de uso:
fonte
public let IS_SIMULATOR = (TARGET_OS_SIMULATOR != 0)
... mesma coisa, simplificada. 1 graçasTARGET_OS_SIMULATOR != 0
está na resposta . É a solução dada por Daniel. Não há necessidade de adicioná-lo novamente em uma variável livre, ele já está lá. Se você acha que tê-lo em uma estrutura é ruim e tê-lo em uma variável livre é melhor, publique um comentário sobre isso ou faça sua própria resposta. Obrigado.Do Xcode 9.3
iOS 9 ou superior:
Swift 3:
Antes do iOS 9:
Objetivo-C:
fonte
will never be executed
avisoSwift 4
Agora você pode usar
targetEnvironment(simulator)
como argumento.Atualizado para o Xcode 9.3
fonte
Deixe-me esclarecer algumas coisas aqui:
TARGET_OS_SIMULATOR
não está definido no código Swift em muitos casos; você pode importá-lo acidentalmente devido a um cabeçalho de ponte, mas isso é quebradiço e não é suportado. Também não é possível em estruturas. É por isso que algumas pessoas estão confusas sobre se isso funciona no Swift.Para executar verificações dinâmicas:
A verificação
ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil
está perfeitamente bem.Você também pode obter o modelo subjacente que está sendo simulado, verificando
SIMULATOR_MODEL_IDENTIFIER
como retornará as stringsiPhone10,3
.Para executar verificações estáticas:
Xcode 9.2 e versões anteriores: defina seu próprio sinalizador de compilação Swift (como mostrado em outras respostas).
O Xcode 9.3+ usa a nova condição targetEnvironment:
fonte
targetEnvironment
parar no Xcode 9.3. Você precisa de uma versão mais recente do Xcode.O que funciona para mim desde o Swift 1.0 é procurar uma arquitetura diferente de arm:
fonte
Tempo de execução, mas mais simples do que a maioria das outras soluções aqui:
Como alternativa, você pode simplesmente chamar uma função auxiliar Objective-C que retorna um booleano que usa a macro do pré-processador (especialmente se você já estiver misturando no seu projeto).
Edit: Não é a melhor solução, especialmente a partir do Xcode 9.3. Veja a resposta do HotJard
fonte
== 0
vez de!= 0
. Usá-lo como descrito acima, mesmo com umelse
bloco depois, não produz nenhum aviso no Swift 4 Xcode Versão 9.2 (9C40b)Nos sistemas modernos:
É fácil.
fonte
TARGET_IPHONE_SIMULATOR
foi descontinuado no iOS 9.TARGET_OS_SIMULATOR
é a substituição. TambémTARGET_OS_EMBEDDED
está disponível.De TargetConditionals.h :
fonte
Espero que esta extensão seja útil.
Uso:
fonte
No Xcode 7.2 (e versões anteriores, mas ainda não testei quanto antes), você pode definir um sinalizador de compilação específico da plataforma "-D TARGET_IPHONE_SIMULATOR" para "Any iOS Simulator".
Procure nas configurações de construção do projeto em "Swift Compiler - Flags do Cliente" e defina o sinalizador em "Other Swift Flags". Você pode definir um sinalizador específico da plataforma clicando no ícone 'mais' quando passar o mouse sobre uma configuração de compilação.
Existem algumas vantagens em fazer isso desta maneira: 1) Você pode usar o mesmo teste condicional ("#if TARGET_IPHONE_SIMULATOR") em seu código Swift e Objective-C. 2) Você pode compilar variáveis que se aplicam apenas a cada build.
Captura de tela das configurações de compilação do Xcode
fonte
Tudo descrito aqui Darwin.TargetConditionals : https://github.com/apple/swift-corelibs-foundation/blob/master/CoreFoundation/Base.subproj/SwiftRuntime/TargetConditionals.h
TARGET_OS_SIMULATOR - Generated code will run under a simulator
fonte
Eu usei esse código abaixo no Swift 3
fonte
Swift 4:
Atualmente, prefiro usar a classe ProcessInfo para saber se o dispositivo é um simulador e que tipo de dispositivo está em uso:
Mas, como você sabe,
simModelCode
não é um código confortável para entender imediatamente que tipo de simulador foi lançado; portanto, se necessário, você pode tentar ver essa outra resposta do SO para determinar o modelo atual do iPhone / dispositivo e ter uma experiência mais humana. string legível.fonte
Aqui está um exemplo do Xcode 11 Swift baseado na incrível resposta do HotJard acima , que também adiciona um
isDevice
Bool e usa emSIMULATOR_UDID
vez do nome. As atribuições variáveis são feitas em cada linha, para que você possa examiná-las mais facilmente no depurador, se desejar.Há também a entrada do dicionário
DTPlatformName
que deve contersimulator
.fonte
Use este código abaixo:
Trabalhos para
Swift 4
eXcode 9.4.1
fonte
Xcode 11, Swift 5
fonte
Além de outras respostas.
No Objective-c, verifique se você incluiu TargetConditionals .
#include <TargetConditionals.h>
antes de usar
TARGET_OS_SIMULATOR
.fonte