내 앱이 iPhone 시뮬레이터에서 실행 중인지 프로그래밍 방식으로 확인하려면 어떻게해야합니까?


270

질문에서 알 수 있듯이 주로 내 코드가 시뮬레이터에서 실행 중인지 여부를 알고 싶지만 실행 중이거나 시뮬레이션중인 특정 iPhone 버전을 알고 싶어합니다.

편집 : 질문 이름에 '프로그래밍 방식으로'라는 단어를 추가했습니다. 내 질문의 요점은 실행중인 버전 / 시뮬레이터에 따라 코드를 동적으로 포함 / 제외 할 수 있기 때문에 실제로이 정보를 제공 할 수있는 전 프로세서 지시문과 같은 것을 찾고 있습니다.


전 프로세서 지시문이 동적인지 확실하지 않습니다 (어쨌든 찾고있는 것일 수도 있습니다). 이 지시문은 빌드 할 때 실제로 실행될 위치를 알고 있다는 것을 의미합니다.
WiseOldDuck

답변:


356

이미 요청했지만 제목이 매우 다릅니다.

iPhone을 컴파일 할 때 Xcode에서 #define을 설정하는 것

나는 거기에서 내 대답을 반복 할 것이다.

SDK 문서의 "조건부 소스 코드 컴파일"에 있습니다.

관련 정의는 TARGET_OS_SIMULATOR이며, 이는 iOS 프레임 워크의 /usr/include/TargetConditionals.h에 정의되어 있습니다. 이전 버전의 툴체인에서는 다음과 같이 작성해야했습니다.

#include "TargetConditionals.h"

그러나 현재 (Xcode 6 / iOS8) 툴체인에서는 더 이상 필요하지 않습니다.

예를 들어 장치에서 실행 중인지 확인하려면 수행해야합니다.

#if TARGET_OS_SIMULATOR
    // Simulator-specific code
#else
    // Device-specific code
#endif

사용 사례에 적합한 방법에 따라


1
감사. 나는 이것이 당신의 원래 질문의 더 구체적인 버전이라는 것에 동의합니다. 당신이 내 원래 검색에서 나온다면 물어볼 필요조차 없었을 것입니다.
Jeffrey Meyer

5
이러한 정의에주의하십시오. 메뉴 항목 '프로젝트> 활성 SDK 설정> 시뮬레이터…'로 코드를 컴파일 할 때 TARGET_IPHONE_SIMULATOR로 TARGET_OS_IPHONE 변수가 모두 정의되었습니다! 따라서 논리를 분리하는 올바른 방법은 Pete (Thanks dude)가 지적합니다.
Vadim

5
#if와 #ifdef의 차이점을 살펴보십시오. 저에게는 잘못된 행동의 원인이었습니다.
Anton

7
아마도 이것이 작성된 이후 TargetConditionals를 포함시킬 필요성이 사라 졌을 수도 있지만 #if TARGET_IPHONE_SIMULATOR가 TargetConditionals.h를 포함하지 않고 작동한다는 사실에 주목하고 싶었습니다.
dmur

1
@Dimitris 좋은 습관입니다. 당신은 TARGET_OS_SIMULATOR이 때문에, 정의 된 방법을 모른다 (TARGET_OS_SIMULATOR) TARGET_OS_SIMULATOR 일치하지 않을 수 있습니다!
Airsource 회사

106

업데이트 된 코드 :

이것은 공식적으로 작동하도록되어 있습니다.

#if TARGET_IPHONE_SIMULATOR
NSString *hello = @"Hello, iPhone simulator!";
#elif TARGET_OS_IPHONE
NSString *hello = @"Hello, device!";
#else
NSString *hello = @"Hello, unknown target!";
#endif

원래 게시물 (더 이상 사용되지 않으므로)

이 코드는 시뮬레이터에서 실행 중인지 알려줍니다.

#ifdef __i386__
NSLog(@"Running in the simulator");
#else
NSLog(@"Running on a device");
#endif

7
iOS 8 및 Xcode 6.1.1부터 TARGET_OS_IPHONE은 시뮬레이터에서 true입니다.
malhal

3
새로운 XCode 버전에서는 더 이상 문제가되지 않습니다.
Fabio Napodano

1
2016 년에 64 비트 시뮬레이터를 실행하지 않는 한. 또는 2019 년 Intel 프로세서가 장착 된 iPhone에서 코드를 실행하십시오.
gnasher729

61

전 처리기 지시문은 아니지만 이것이 내가이 질문에 왔을 때 찾고 있던 것입니다.

NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
    //device is simulator
}

9
[model compare:iPhoneSimulator] == NSOrderedSame작성[model isEqualToString:iPhoneSimulator]
user102008

18
또는 [model hasSuffix:@"Simulator"]일반적으로 "시뮬레이터"에만 관심이 있다면, 특히 iPhone 또는 iPad 는 아닙니다 . 이 답변은 iPad 시뮬레이터에서 작동하지 않습니다 :)
Nuthatch

Nuthatch의 의견이 이것이 토토에서 가장 좋은 답변이되기 때문에 공감되었습니다.
Le Mot Juiced

12
iOS9에서namemodel
n

1
사용자가 Simulator자신의 장치 이름에 단어를 추가하면 코드가 작동하지 않습니다
mbelsky

55

이를 수행하는 가장 좋은 방법은 다음과 같습니다.

#if TARGET_IPHONE_SIMULATOR

그리고 아닙니다

#ifdef TARGET_IPHONE_SIMULATOR

항상 정의 된 이후 : 0 또는 1


39

더 나은 길은 지금 있습니다!

Xcode 9.3 베타 4 #if targetEnvironment(simulator)부터 확인할 수 있습니다 .

#if targetEnvironment(simulator)
//Your simulator code
#endif

업데이트
Xcode 10 및 iOS 12 SDK도이를 지원합니다.


1
이것은 나에게 유일한 해결책이며 나머지 솔루션은 효과가 없었습니다.
Vrutin Rathod

참고 이것은 신속합니다.
Matt S.

35

Swift의 경우 다음을 구현할 수 있습니다.

구조화 된 데이터를 만들 수있는 구조체를 만들 수 있습니다

struct Platform {
    static var isSimulator: Bool {
        #if targetEnvironment(simulator)
            // We're on the simulator
            return true
        #else
            // We're on a device
             return false
        #endif
    }
}

그런 다음 Swift에서 장치 또는 시뮬레이터 용 앱이 빌드되고 있는지 감지하려면.

if Platform.isSimulator {
    // Do one thing
} else {
    // Do the other
}

제 생각에는 가장 깨끗한 구현이며 x86_64 및 i386 아키텍처를 설명합니다. Core Data에서 이상한 장치 대 시뮬레이터 버그를 극복하는 데 도움이되었습니다. 당신은 남자입니다!
Iron John Bonney

5
운동장에서는 "반환 후 코드가 실행되지 않습니다"라는 경고가 표시됩니다. 그래서 나는 #if #else #endif더 나을 것이라고 생각 합니다.
DawnSong

12

작품 Swift 5Xcode 11.3.1

이 코드를 사용하십시오 :

#if targetEnvironment(simulator)
   // Simulator
#else
   // Device
#endif

9

모든 대답은 훌륭하지만 컴파일 검사와 런타임 검사를 명확히하지 않기 때문에 어떻게 든 저와 초보자를 혼동합니다. 전처리 기는 컴파일 시간 이전이지만 더 명확하게 만들어야합니다.

이 블로그 기사는 iPhone 시뮬레이터를 감지하는 방법을 보여줍니다 . 분명히

실행 시간

우선, 간단히 논의 해 봅시다. UIDevice는 이미 장치에 대한 정보를 제공합니다

[[UIDevice currentDevice] model]

앱이 실행중인 위치에 따라 "iPhone Simulator"또는 "iPhone"을 반환합니다.

컴파일 시간

그러나 원하는 것은 컴파일 시간 정의를 사용하는 것입니다. 왜? 시뮬레이터 내부 또는 장치에서 실행되도록 앱을 엄격하게 컴파일하기 때문입니다. Apple은이라는 정의를 만듭니다 TARGET_IPHONE_SIMULATOR. 코드를 보자.

#if TARGET_IPHONE_SIMULATOR

NSLog(@"Running in Simulator - no app store or giro");

#endif

1
다른 답변에서 어떻게 개선됩니까?
user151019

@Mark 그것은 조금 명확 해집니다
onmyway133

5
현재 Xcode 7에서 iOS 9 Simulator [[UIDevice currentDevice] model]iPhone대신을 반환 iPhone Simulator합니다. 따라서 이것이 최선의 방법은 아니라고 생각합니다.
eMdOS

6

이전 답변은 약간 날짜가 있습니다. TARGET_IPHONE_SIMULATOR매크로를 쿼리하기 만하면됩니다 ( 다른 헤더 파일을 포함 할 필요가 없습니다 ( iOS 용으로 코딩한다고 가정)).

시도 TARGET_OS_IPHONE했지만 실제 장치 및 시뮬레이터에서 실행할 때 동일한 값 (1)을 반환했기 때문에 TARGET_IPHONE_SIMULATOR대신 사용 하는 것이 좋습니다 .


TARGET_OS_IPHONE은 iOS 또는 MacOS X에서 실행될 수있는 코드를위한 것입니다. 분명히 해당 코드가 시뮬레이터에서 "iPhone"방식으로 작동하기를 원할 것입니다.
gnasher729


4

저도 같은 문제를 겪고, 모두 TARGET_IPHONE_SIMULATORTARGET_OS_IPHONE항상 정의, 그리고 물론 1 피트의 솔루션 작품에 설정되지만으로 안전, 여기의 뭔가를 당신은 이제까지 인텔이 아닌 다른 무언가에 빌드로 발생 (가능성,하지만 누가 알 겠어) 경우 아이폰 하드웨어가 변경되지 않는 한 (코드는 항상 현재 존재하는 아이폰에서 작동합니다) :

#if defined __arm__ || defined __thumb__
#undef TARGET_IPHONE_SIMULATOR
#define TARGET_OS_IPHONE
#else
#define TARGET_IPHONE_SIMULATOR 1
#undef TARGET_OS_IPHONE
#endif

편리한 곳에두고 TARGET_*상수가 올바르게 정의 된 척하십시오 .


4

누구든지 여기에 제공된 대답을 고려 했습니까?

objective-c에 해당하는 것으로 가정합니다.

+ (BOOL)isSimulator {
    NSOperatingSystemVersion ios9 = {9, 0, 0};
    NSProcessInfo *processInfo = [NSProcessInfo processInfo];
    if ([processInfo isOperatingSystemAtLeastVersion:ios9]) {
        NSDictionary<NSString *, NSString *> *environment = [processInfo environment];
        NSString *simulator = [environment objectForKey:@"SIMULATOR_DEVICE_NAME"];
        return simulator != nil;
    } else {
        UIDevice *currentDevice = [UIDevice currentDevice];
        return ([currentDevice.model rangeOfString:@"Simulator"].location != NSNotFound);
    }
}

4

스위프트 4.2 / xCode 10

UIDevice에서 확장을 만들었으므로 시뮬레이터가 실행 중인지 쉽게 요청할 수 있습니다.

// UIDevice+CheckSimulator.swift

import UIKit

extension UIDevice {

    /// Checks if the current device that runs the app is xCode's simulator
    static func isSimulator() -> Bool {        
        #if targetEnvironment(simulator)
            return true
        #else
            return false
        #endif
    }
}

예를 들어 내 AppDelegate 에서이 방법을 사용하여 시뮬레이터에 불가능한 원격 알림을 등록해야하는지 결정합니다.

// CHECK FOR REAL DEVICE / OR SIMULATOR
if UIDevice.isSimulator() == false {

    // REGISTER FOR SILENT REMOTE NOTIFICATION
    application.registerForRemoteNotifications()
}

1

모든 유형의 "시뮬레이터"를 포함하려면

NSString *model = [[UIDevice currentDevice] model];
if([model rangeOfString:@"Simulator" options:NSCaseInsensitiveSearch].location !=NSNotFound)
{
    // we are running in a simulator
}

4
Xcode 7과는 아무런 관련이 없습니다. Xcode 7의 iOS8로 iOS Simulator를 실행하면 작동합니다. iOS9 것은하지 않습니다 일 경우 [[UIDevice currentDevice] 모델] 만 반환 "아이폰"응용 프로그램은 iOS 시뮬레이터에서 발사 된 경우
테슬라

왜 안돼 -[NSString containsString]?
Gobe

1

Swift 4.2 (Xcode 10)를 사용하면이 작업을 수행 할 수 있습니다

#if targetEnvironment(simulator)
  //simulator code
#else 
  #warning("Not compiling for simulator")
#endif

1
또 다른 사본 붙여 넣기
J. Doe

0

내 대답은 @Daniel Magnusson 답변과 @Nuthatch 및 @ n.Drake의 의견을 기반으로합니다. iOS9 이상에서 작업하는 신속한 사용자를 위해 시간을 절약하기 위해 작성했습니다.

이것이 나를 위해 일한 것입니다.

if UIDevice.currentDevice().name.hasSuffix("Simulator"){
    //Code executing on Simulator
} else{
    //Code executing on Device
}

1
사용자가 Simulator자신의 장치 이름에 단어를 추가하면 코드가 작동하지 않습니다
mbelsky

불행히도 XCode 8 UIDevice.current.name에서는 시뮬레이터가 실행되는 시스템의 이름 (일반적으로 "Simon 's MacBook Pro"와 같은 이름)이보고되어 테스트를 신뢰할 수 없게되었습니다. 나는 여전히 그것을 고칠 수있는 깨끗한 방법을 찾고 있습니다.
Michael

0

/// 시뮬레이터가 아닌 장치 인 경우 true를 리턴합니다.

public static var isSimulator: Bool {
    #if (arch(i386) || arch(x86_64)) && os(iOS)
        return true
    #else
        return false
    #endif
}

0

Apple은 앱이 시뮬레이터를 대상으로하는지 확인하기위한 지원을 다음과 같이 추가했습니다.

#if targetEnvironment(simulator)
let DEVICE_IS_SIMULATOR = true
#else
let DEVICE_IS_SIMULATOR = false
#endif

0

아무것도 효과가 없다면 이것을 시도하십시오

public struct Platform {

    public static var isSimulator: Bool {
        return TARGET_OS_SIMULATOR != 0 // Use this line in Xcode 7 or newer
    }

}

-4

내 의견으로는, 대답 (위에 제시되고 아래에 반복) :

NSString *model = [[UIDevice currentDevice] model];
if ([model isEqualToString:@"iPhone Simulator"]) {
    //device is simulator
}

런타임에 분명히 실행되고 COMPILE DIRECTIVE이기 때문에 가장 좋은 대답입니다.


11
동의하지 않습니다. 이 코드는 제품에서 끝나지만 컴파일러 지시문은 장치의 불필요한 부분을 일상적으로 유지합니다.
9 개의 돌

1
컴파일러 지시어는 장치와 시뮬레이터가 완전히 다른 컴파일 대상이기 때문에 작동합니다. 즉, 둘 다 동일한 바이너리를 사용하지 않습니다. 그것은 다른 하드웨어로 컴파일 할, 그래서 그 경우에 의미가 있습니다.
Brad Parks

RUNTIME에서 실행되면 최악의 답변이됩니다.
gnasher729

-4

이것은 나를 위해 최선을 다했다

NSString *name = [[UIDevice currentDevice] name];


if ([name isEqualToString:@"iPhone Simulator"]) {

}

2
Xcode 7.3에서 iPhone 6 Plus Simulator는을 반환합니다 "iPhone".
Eric
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.