วิธีการตรวจสอบว่ามีการสร้างแอปสำหรับอุปกรณ์หรือเครื่องมือจำลองใน Swift


277

ใน Objective-C เรารู้ได้ว่ามีการสร้างแอปสำหรับอุปกรณ์หรือเครื่องมือจำลองโดยใช้มาโครหรือไม่:

#if TARGET_IPHONE_SIMULATOR
    // Simulator
#else
    // Device
#endif

นี่คือมาโครเวลารวบรวมและไม่สามารถใช้งานได้ในขณะใช้งานจริง

ฉันจะประสบความสำเร็จในสวิฟท์ได้อย่างไร


2
นั่นไม่ใช่วิธีการตรวจจับตัวจำลองหรืออุปกรณ์จริง ณ รันไทม์ใน Objective-C นั่นคือคำสั่งคอมไพเลอร์ที่ส่งผลให้รหัสแตกต่างกันขึ้นอยู่กับการสร้าง
rmaddy

ขอบคุณ ฉันแก้ไขคำถามของฉัน
RaffAl

9
คำตอบที่โหวตมากที่สุดไม่ใช่วิธีที่ดีที่สุดในการแก้ปัญหานี้! คำตอบของ mbelsky (ขณะนี้ไกลมาก) เป็นทางออกเดียวที่ไม่มีข้อผิดพลาดใด ๆ แม้แต่ Greg Parker จาก Apple ก็แนะนำให้ทำเช่นนั้น: lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/…
jan.vogt

1
แม้ใน CAPS มันเป็นสิ่งที่ดีที่สุดที่มีอะไรผิดปกติกับการตรวจสอบเป็นประจำ คำแนะนำจากวิศวกรของ Apple มักจะเป็นขยะที่คิดไม่ดีหรือใช้ในบางสถานการณ์เท่านั้นดังนั้น initself จึงมีความหมายน้อยกว่าไม่มีอะไรเลย
Fattie

1
@Fattie: มันน่าสนใจที่จะรู้ว่าทำไมไม่มีคำตอบใดที่ตรงกับความต้องการของคุณและสิ่งที่คุณคาดหวังอย่างแท้จริงจากการมอบรางวัล
Martin R

คำตอบ:


364

อัปเดต 30/01/19

ในขณะที่คำตอบนี้อาจใช้งานได้โซลูชันที่แนะนำสำหรับการตรวจสอบแบบคงที่ (ตามที่วิศวกรหลายคนอธิบายไว้) คือการกำหนดธงคอมไพเลอร์ที่กำหนดเองซึ่งกำหนดเป้าหมายไปที่ iOS Simulators สำหรับคำแนะนำรายละเอียดเกี่ยวกับวิธีการทำเพื่อให้ดูคำตอบ @ mbelsky ของ

คำตอบเดิม

หากคุณต้องการตรวจสอบแบบคงที่ (เช่นไม่ใช่รันไทม์หาก / อื่น ๆ ) คุณไม่สามารถตรวจสอบเครื่องมือจำลองได้โดยตรง แต่คุณสามารถตรวจพบ iOS บนสถาปัตยกรรมเดสก์ทอปดังต่อไปนี้

#if (arch(i386) || arch(x86_64)) && os(iOS)
    ...
#endif

หลังจากรุ่นSwift 4.1

การใช้งานล่าสุดตอนนี้โดยตรงสำหรับทุกเงื่อนไขในการจำลองทุกประเภทต้องใช้เพียงหนึ่งเงื่อนไข -

#if targetEnvironment(simulator)
  // your simulator code
#else
  // your real device code
#endif

หากต้องการคำชี้แจงเพิ่มเติมคุณสามารถตรวจสอบข้อเสนอSwift SE-0190


สำหรับรุ่นเก่า -

เห็นได้ชัดว่านี่เป็นเท็จบนอุปกรณ์ แต่จะคืนค่าจริงสำหรับ iOS Simulator ตามที่ระบุในเอกสารประกอบ :

คอนฟิกูเรชันการบิวด์ arch (i386) จะส่งคืนค่าจริงเมื่อโค้ดถูกคอมไพล์สำหรับเครื่องจำลอง iOS 32 บิต

หากคุณกำลังพัฒนาโปรแกรมจำลองอื่นที่ไม่ใช่ iOS คุณสามารถเปลี่ยนแปลงosพารามิเตอร์ได้เช่น:

ตรวจจับการจำลองwatchOS

#if (arch(i386) || arch(x86_64)) && os(watchOS)
...
#endif

ตรวจจับโปรแกรมจำลองtvOS

#if (arch(i386) || arch(x86_64)) && os(tvOS)
...
#endif

หรือแม้แต่ตรวจจับการจำลองใด ๆ

#if (arch(i386) || arch(x86_64)) && (os(iOS) || os(watchOS) || os(tvOS))
...
#endif

หากคุณใช้โอเคกับการตรวจสอบรันไทม์คุณสามารถตรวจสอบTARGET_OS_SIMULATORตัวแปร (หรือTARGET_IPHONE_SIMULATORใน iOS 8 และต่ำกว่า) ซึ่งเป็นความจริงในเครื่องจำลอง

โปรดสังเกตว่าสิ่งนี้แตกต่างและ จำกัด กว่าการใช้แฟล็กตัวประมวลผลก่อนเล็กน้อย ตัวอย่างเช่นคุณจะไม่สามารถใช้งานได้ในสถานที่ที่ a if/elseไม่ถูกต้องทางไวยากรณ์ (เช่นนอกขอบเขตฟังก์ชั่น)

ตัวอย่างเช่นคุณต้องการให้มีการนำเข้าที่แตกต่างกันบนอุปกรณ์และในเครื่องจำลอง นี่เป็นไปไม่ได้ด้วยการตรวจสอบแบบไดนามิกในขณะที่มันเป็นเรื่องเล็กน้อยกับการตรวจสอบแบบคงที่

#if (arch(i386) || arch(x86_64)) && os(iOS)
  import Foo
#else
  import Bar
#endif

นอกจากนี้เนื่องจากแฟล็กถูกแทนที่ด้วย a 0หรือ a 1โดยตัวประมวลผลก่อน swift หากคุณใช้โดยตรงในif/elseนิพจน์คอมไพเลอร์จะเพิ่มคำเตือนเกี่ยวกับโค้ดที่เข้าไม่ถึง

เพื่อที่จะหลีกเลี่ยงคำเตือนนี้ดูคำตอบอีกข้อหนึ่ง


1
เพิ่มเติมอ่านที่นี่ arch(i386) && os(iOS)และจะยิ่งเข้มงวดมากขึ้นคุณสามารถใช้
ahruss

1
สิ่งนี้ไม่ได้ผลสำหรับฉัน ฉันต้องตรวจสอบทั้ง i386 และ x86_64
akaru

3
คำตอบนี้ไม่ใช่วิธีที่ดีที่สุดในการแก้ปัญหานี้! คำตอบของ mbelsky (ปัจจุบันอยู่ไกลมาก) เป็นทางออกเดียวที่ไม่มีข้อผิดพลาดใด ๆ แม้แต่ Greg Parker จาก Apple ก็แนะนำให้ทำเช่นนั้น: lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/…
jan.vogt

2
@russbishop สิ่งนี้พิสูจน์แล้วว่าเป็นคำแนะนำที่เป็นประโยชน์ต่อคนหลายร้อยคนเพื่อชดเชย API ที่ขาดหายไป แทนที่จะแย่งชิงคำตอบโดยการลงชื่อความคิดเห็นด้านบนเพียงแค่สื่อสาร ฉันอัปเดตคำตอบเพื่อให้ความกระจ่างว่านี่ไม่ใช่วิธีแก้ปัญหาที่ทันสมัยอีกต่อไปและฉันได้ให้ลิงก์ไปยังคำตอบที่ถูกต้องมากขึ้น
Gabriele Petronella

9
ใน Swift 4.1 คุณจะสามารถพูดได้#if targetEnvironment(simulator):) ( github.com/apple/swift-evolution/blob/master/proposals/… )
Hamish

172

ล้าสมัยสำหรับ SWIFT 4.1 ใช้#if targetEnvironment(simulator)แทน แหล่ง

ในการตรวจจับโปรแกรมจำลองใน Swift คุณสามารถใช้การกำหนดค่าการสร้าง

  • กำหนดการตั้งค่านี้-D IOS_SIMULATORในSwift Compiler - Custom Flags> Swift Flags อื่น ๆ
  • เลือกiOS Simulator SDK ใดก็ได้ในดรอปดาวน์นี้รายการแบบหล่นลง

ตอนนี้คุณสามารถใช้คำสั่งนี้เพื่อตรวจจับการจำลอง:

#if IOS_SIMULATOR
    print("It's an iOS Simulator")
#else
    print("It's a device")
#endif

นอกจากนี้คุณสามารถขยายคลาส UIDevice:

extension UIDevice {
    var isSimulator: Bool {
        #if IOS_SIMULATOR
            return true
        #else
            return false
        #endif
    }
}
// Example of usage: UIDevice.current.isSimulator

8
นี่ควรเป็นคำตอบที่ดีที่สุด! แม้แต่ Greg Parker จาก Apple ก็แนะนำเช่นนั้น: lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/…
jan.vogt

1
อัปเดตการใช้งานสำหรับ swift 3: UIDevice.current.isSimulator
tylernol

1
ฉันขอถามได้ไหมว่าทำไมถ้าฉันเพิ่มสิ่งนี้ภายใต้ปล่อยสิ่งนี้จะไม่ทำงาน
William Hu

3
นี่เป็นคำตอบเดียวที่ถูกต้อง คุณสามารถตั้งค่านี้ในxcconfigไฟล์โดยใช้OTHER_SWIFT_FLAGS = TARGET_OS_EMBEDDEDและOTHER_SWIFT_FLAGS[sdk=embeddedsimulator*] = TARGET_OS_SIMULATORเพื่อแทนที่สำหรับ Simulator
russbishop

1
บน Xcode 9.2 คำตอบนี้ไม่สามารถรวบรวมเวลาได้ การลบ "-" ก่อนที่ "D" จะแก้ไขปัญหาให้ฉันได้
เบลค

160

อัปเดตข้อมูล ณ วันที่ 20 กุมภาพันธ์ 2018

ดูเหมือนว่า @russbishop มีคำตอบที่เชื่อถือได้ซึ่งทำให้คำตอบนี้ "ไม่ถูกต้อง" - แม้ว่ามันจะใช้งานได้นาน

ตรวจสอบว่ามีการสร้างแอปสำหรับอุปกรณ์หรือเครื่องมือจำลองใน Swift

คำตอบก่อนหน้า

จากคำตอบของ @ WZW และความคิดเห็นของ @ Pang ฉันได้สร้างโครงสร้างยูทิลิตี้อย่างง่าย วิธีนี้หลีกเลี่ยงคำเตือนที่เกิดจากคำตอบของ @ WZW

import Foundation

struct Platform {

    static var isSimulator: Bool {
        return TARGET_OS_SIMULATOR != 0
    }

}

ตัวอย่างการใช้งาน:

if Platform.isSimulator {
    print("Running on Simulator")
}

10
ทางออกที่ดีกว่าการยอมรับ แน่นอนว่าถ้าสักวัน (แม้ว่าจะไม่น่าจะเป็นไปได้มาก) Apple ตัดสินใจใช้ i386 หรือ x85_64 บนอุปกรณ์ iOS คำตอบที่ยอมรับจะไม่ทำงาน ... หรือแม้ว่าคอมพิวเตอร์ตั้งโต๊ะจะได้รับ proc ใหม่!
Frizlab

2
ยืนยันว่าสิ่งนี้ทำงานได้อย่างสมบูรณ์บน Xcode 7: public let IS_SIMULATOR = (TARGET_OS_SIMULATOR != 0)... สิ่งเดียวกันเรียบง่าย +1 ด้วยความขอบคุณ
Dan Rosenstark

1
@daniel มันใช้งานได้ดีและจริง ๆ แล้วมันตรงไปตรงมามากกว่าทางออกของฉัน อย่างไรก็ตามมันก็คุ้มค่าที่จะสังเกตว่ามันมี จำกัด มากกว่าขั้นตอนพรีโปรเซสเซอร์ หากคุณต้องการบางส่วนของรหัสที่จะไม่รวมอยู่ในเป้าหมาย (เช่นคุณต้องการเลือกระหว่างการนำเข้าสองครั้งในเวลารวบรวม) คุณต้องใช้การตรวจสอบแบบคงที่ ฉันได้แก้ไขคำตอบของฉันเพื่อเน้นความแตกต่างนี้
Gabriele Petronella

คำตอบนี้ไม่ใช่วิธีที่ดีที่สุดในการแก้ปัญหานี้! คำตอบของ mbelsky (ปัจจุบันอยู่ไกลมาก) เป็นทางออกเดียวที่ไม่มีข้อผิดพลาดใด ๆ แม้แต่ Greg Parker จาก Apple ก็แนะนำให้ทำเช่นนั้น: lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/…
jan.vogt

2
@Fattie TARGET_OS_SIMULATOR != 0มีคำตอบอยู่แล้ว มันเป็นทางออกของแดเนียล ไม่จำเป็นต้องเพิ่มอีกครั้งในตัวแปรอิสระ แต่มีอยู่แล้ว หากคุณคิดว่าการมีมันใน struct นั้นไม่ดีและการมีมันในตัวแปรอิสระดีกว่าให้โพสต์ความคิดเห็นเกี่ยวกับสิ่งนี้หรือตอบคำถามของคุณเอง ขอบคุณ
Eric Aya

69

จาก Xcode 9.3

#if targetEnvironment(simulator)

Swift สนับสนุนแพลตฟอร์มเงื่อนไข targetEnvironment ใหม่ด้วยการจำลองอาร์กิวเมนต์ที่ถูกต้องเพียงครั้งเดียว การคอมไพล์ตามเงื่อนไขของรูปแบบ '#if targetEnvironment (โปรแกรมจำลอง)' สามารถใช้เพื่อตรวจจับได้เมื่อเป้าหมายการสร้างเป็นเครื่องจำลอง คอมไพเลอร์ Swift จะพยายามตรวจจับเตือนและแนะนำการใช้ targetEnvironment (โปรแกรมจำลอง) เมื่อประเมินสภาพของแพลตฟอร์มที่ดูเหมือนว่าเป็นการทดสอบสภาพแวดล้อมจำลองโดยทางอ้อมผ่านเงื่อนไขแพลตฟอร์ม os () และ arch () ที่มีอยู่ (SE-0190)

iOS 9+:

extension UIDevice {
    static var isSimulator: Bool {
        return NSProcessInfo.processInfo().environment["SIMULATOR_DEVICE_NAME"] != nil
    }
}

สวิฟท์ 3:

extension UIDevice {
    static var isSimulator: Bool {
        return ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil
    }
}

ก่อน iOS 9:

extension UIDevice {
    static var isSimulator: Bool {
        return UIDevice.currentDevice().model == "iPhone Simulator"
    }
}

Objective-C:

@interface UIDevice (Additions)
- (BOOL)isSimulator;
@end

@implementation UIDevice (Additions)

- (BOOL)isSimulator {
    if([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){9, 0, 0}]) {
        return [NSProcessInfo processInfo].environment[@"SIMULATOR_DEVICE_NAME"] != nil;
    } else {
        return [[self model] isEqualToString:@"iPhone Simulator"];
    }
}

@end

2
การเปรียบเทียบสตริงนั้นบอบบางกว่าการใช้ค่าคงที่ที่กำหนดไว้
Michael Peterson

@ P1X3L5 คุณพูดถูก! แต่ฉันคิดว่าวิธีการนี้เรียกว่าในโหมดดีบั๊ก - มันไม่สามารถแข็งได้ แต่จะเพิ่มในโปร
เจ

1
@GantMan ขอบคุณสำหรับการตอบสนอง ฉันแก้ไขรหัสแล้ว
HotJard

@HotJard ดีคนนี้ไม่ได้will never be executedเตือน
Dannie P

59

สวิฟต์ 4

ตอนนี้คุณสามารถใช้targetEnvironment(simulator)เป็นอาร์กิวเมนต์

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

อัปเดตสำหรับ Xcode 9.3


8
ตอนนี้ควรเป็นคำตอบที่ยอมรับได้ ฉันหวังว่าจะมีวิธีใน SO เพื่อเสนอคำตอบที่แนะนำใหม่ตามการปรับปรุงของ OS / ภาษาการเขียนโปรแกรม
quemeful

4
มันเป็นจุดที่ดี @quemeful - เป็นหนึ่งในความล้มเหลวพื้นฐานของ SO ตั้งแต่ระบบคอมพิวเตอร์เปลี่ยนแปลงอย่างรวดเร็วเกือบคำตอบเพื่อให้ทุกกลายเป็นช่วงเวลาที่ไม่ถูกต้อง
Fattie

40

ให้ฉันอธิบายบางสิ่งที่นี่:

  1. TARGET_OS_SIMULATORไม่ได้ตั้งค่าในรหัส Swift ในหลายกรณี คุณอาจได้รับการนำเข้าโดยไม่ได้ตั้งใจเนื่องจากส่วนหัวการเชื่อมโยง แต่มันเปราะและไม่รองรับ นอกจากนี้ยังเป็นไปไม่ได้ในกรอบ นี่คือสาเหตุที่บางคนสับสนว่าการทำงานในสวิฟท์
  2. ฉันขอแนะนำอย่างยิ่งให้ไม่ใช้สถาปัตยกรรมแทนตัวจำลอง

วิธีตรวจสอบแบบไดนามิก:

ตรวจสอบProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nilได้อย่างสมบูรณ์แบบ

นอกจากนี้คุณยังจะได้รับรูปแบบพื้นฐานที่ถูกจำลองโดยการตรวจสอบซึ่งจะกลับมาเหมือนสตริงSIMULATOR_MODEL_IDENTIFIERiPhone10,3

วิธีตรวจสอบแบบสแตติก:

Xcode 9.2 และรุ่นก่อนหน้า: กำหนดธงการรวบรวม Swift ของคุณเอง (ดังที่แสดงในคำตอบอื่น ๆ )

Xcode 9.3+ ใช้เงื่อนไข targetEnvironment ใหม่:

#if targetEnvironment(simulator)
    // for sim only
#else
    // for device
#endif

1
ดูเหมือนว่าคุณมีข้อมูลภายในใหม่ที่นี่ มีประโยชน์มาก! หมายเหตุ TARGET_OS_SIMULATOR ทำงานได้ทั้งในแอพและรหัสเฟรมเวิร์ก และมันยังทำงานใน Xcode 9.3 b3 แต่ฉันเดาว่านี่เป็น "อุบัติเหตุ" ชนิดของคนเกียจคร้าน เพราะนี่เป็นวิธีที่แฮ็กน้อยที่สุด ในฐานะผู้ให้บริการของรหัสเฟรมเวิร์กที่สามารถรวบรวมได้ใน Xcode 9.3 หรือก่อนหน้าดูเหมือนว่าเราจะต้องห่อ #if targetEnvironment ... ใน #if swift (> = 4.1) เพื่อหลีกเลี่ยงข้อผิดพลาดของคอมไพเลอร์ หรือฉันเดาว่าจะใช้ .... สภาพแวดล้อม ["SIMULATOR_DEVICE_NAME"]! = ไม่มี การตรวจสอบนี้ดูเหมือนแฮ็คมากขึ้น IMO
แดเนียล

หากมี "เงื่อนไขแพลตฟอร์มที่ไม่คาดคิด (คาดว่า 'os', 'arch' หรือ 'swift')" ใช้ errorEnvironment (ตัวจำลอง)
Zaporozhchenko Oleksandr

@Aleksandr targetEnvironmentลงจอดใน Xcode 9.3 คุณต้องมี Xcode เวอร์ชันที่ใหม่กว่า
russbishop

@russbishop งานที่ดีช่วยล้างสิ่งนี้สำหรับยุคใหม่ล่าสุด - ขอบคุณ!
Fattie

ฉันส่ง 250 ค่าหัวเนื่องจากคำตอบนี้ดูเหมือนจะเพิ่มข้อมูลที่ใหม่และ
ทันสมัย

15

อะไรที่เหมาะกับฉันตั้งแต่ Swift 1.0 กำลังตรวจสอบสถาปัตยกรรมอื่นที่ไม่ใช่แขน:

#if arch(i386) || arch(x86_64)

     //simulator
#else 
     //device

#endif

14

รันไทม์ แต่เรียบง่ายกว่าโซลูชันอื่น ๆ ส่วนใหญ่ที่นี่:

if TARGET_OS_SIMULATOR != 0 {
    // target is current running in the simulator
}

หรือคุณสามารถเรียกฟังก์ชันผู้ช่วย Objective-C ที่ส่งคืนบูลีนที่ใช้มาโครตัวประมวลผลก่อน (โดยเฉพาะถ้าคุณผสมอยู่ในโครงการของคุณ)

แก้ไข: ไม่ใช่โซลูชันที่ดีที่สุดโดยเฉพาะอย่างยิ่ง Xcode 9.3 ดูคำตอบของ HotJard


3
ฉันทำเช่นนี้ แต่รับคำเตือนในข้ออื่นเพราะมัน "จะไม่ถูกดำเนินการ" เรามีกฎการเตือนที่เป็นศูนย์ดังนั้น :-(
EricS

มันจะแสดงคำเตือน แต่มันสมเหตุสมผลถ้าคุณมีตัวจำลองหรืออุปกรณ์ที่เลือกไว้สำหรับการสร้างคำเตือนจะแสดงในส่วนที่จะไม่ถูกประหาร แต่ใช่น่ารำคาญสำหรับนโยบายการเตือนศูนย์
Fonix

1
เห็นเพียงคำเตือนเมื่อฉันใช้แทน== 0 != 0การใช้งานตามที่เขียนไว้ด้านบนแม้ว่าจะมีelseบล็อกอยู่ก็ตาม แต่ก็ไม่ได้สร้างคำเตือนใด ๆ ใน Swift 4 Xcode เวอร์ชั่น 9.2 (9C40b)
shim

นอกจากนี้ฉันทดสอบว่าใช้กับเครื่องจำลองเป้าหมายและอุปกรณ์ทางกายภาพ ดูเหมือนว่าจะเหมือนกันใน Swift 3.2 (รุ่น Xcode เดียวกัน)
ชิม

ใน Xcode 9.3 + Swift 4.1 ฉันเพิ่งสังเกตเห็นว่ามันมีคำเตือนแม้ด้วย! = 0 Sheesh
ชิม

10

ในระบบที่ทันสมัย:

#if targetEnvironment(simulator)
    // sim
#else
    // device
#endif

มันเป็นเรื่องง่าย


1
ไม่แน่ใจว่าทำไมคนแรกที่ควรจะเป็น "ที่ถูกต้องมากขึ้น" กว่าคำตอบของแดเนียล - โปรดทราบว่าคนที่สองคือการตรวจสอบรวบรวมเวลา สวัสดีปีใหม่!
Martin R

5

TARGET_IPHONE_SIMULATORเลิกใช้แล้วใน iOS 9 TARGET_OS_SIMULATORเป็นการทดแทน ยังTARGET_OS_EMBEDDEDสามารถใช้ได้

จากTargetConditionals.h :

#if defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__MACOS_CLASSIC__) )
. . .
#define TARGET_OS_SIMULATOR         0
#define TARGET_OS_EMBEDDED          1 
#define TARGET_IPHONE_SIMULATOR     TARGET_OS_SIMULATOR /* deprecated */
#define TARGET_OS_NANO              TARGET_OS_WATCH /* deprecated */ 

1
ฉันลอง TARGET_OS_SIMULATOR แต่ไม่ทำงานหรือรับรู้โดย Xcode ในขณะที่ TARGET_IPHONE_SIMULATOR ทำ ฉันกำลังสร้าง iOS 8.0 ขึ้นไป
CodeOverRide

ฉันกำลังดูส่วนหัวของ iOS 9 ฉันจะอัปเดตคำตอบของฉัน
Nuthatch

5

ฉันหวังว่าส่วนขยายนี้จะมีประโยชน์

extension UIDevice {
    static var isSimulator: Bool = {
        #if targetEnvironment(simulator)
        return true
        #else
        return false
        #endif
    }()
}

การใช้งาน:

if UIDevice.isSimulator {
    print("running on simulator")
}

@ChetanKoli ฉันจะทำโค้ดให้ชัดเจนมากกว่าสั้นเพื่อให้ทุกคนเข้าใจได้ง่าย ไม่แน่ใจว่าฉันรู้สึกอย่างไรเกี่ยวกับการแก้ไขของคุณ
ลูคัส Chwe

3

ใน Xcode 7.2 (และก่อนหน้านี้ แต่ฉันยังไม่ได้ทดสอบก่อนหน้านี้เท่าไหร่) คุณสามารถตั้งค่าสถานะการ build เฉพาะแพลตฟอร์ม "-D TARGET_IPHONE_SIMULATOR" สำหรับ "Any iOS Simulator"

ดูในการตั้งค่าการสร้างโครงการภายใต้ "Swift Compiler - Customer Flags" จากนั้นตั้งค่าสถานะใน "Other Swift Flags" คุณสามารถตั้งค่าสถานะเฉพาะแพลตฟอร์มได้โดยคลิกที่ไอคอน 'บวก' เมื่อคุณวางเมาส์เหนือการกำหนดค่าการสร้าง

มีข้อดีสองสามข้อในการทำเช่นนี้: 1) คุณสามารถใช้การทดสอบตามเงื่อนไข ("#if TARGET_IPHONE_SIMULATOR" #) ในรหัส Swift และ Objective-C ของคุณ 2) คุณสามารถรวบรวมตัวแปรที่ใช้กับแต่ละบิลด์เท่านั้น

ภาพหน้าจอการตั้งค่าการสร้าง Xcode



1

ฉันใช้โค้ดด้านล่างนี้ใน Swift 3

if TARGET_IPHONE_SIMULATOR == 1 {
    //simulator
} else {
    //device
}

1
ฉันทำเช่นนี้ แต่รับคำเตือนในข้ออื่นเพราะมัน "จะไม่ถูกดำเนินการ" เรามีกฎการเตือนเป็นศูนย์ดังนั้น grrrr ....
EricS

มันจะแสดงคำเตือนเมื่อใดก็ตามที่คุณพยายามที่จะเรียกใช้กับอุปกรณ์หากคุณได้รับเลือกให้จำลองการทำงานมันจะไม่แสดงคำเตือน
ak_ninan

1
เลิกใช้แล้ว
rcmstark

1

สวิฟท์ 4:

ปัจจุบันฉันต้องการใช้คลาสProcessInfoเพื่อทราบว่าอุปกรณ์เป็นอุปกรณ์จำลองและอุปกรณ์ชนิดใดที่ใช้งานอยู่:

if let simModelCode = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
            print("yes is a simulator :\(simModelCode)")
}

แต่อย่างที่คุณรู้simModelCodeไม่ใช่รหัสที่สะดวกสบายที่จะเข้าใจในทันทีซึ่งชนิดของการจำลองได้เปิดตัวดังนั้นหากคุณต้องการคุณสามารถลองดูคำตอบอื่น ๆ ของ SO เพื่อพิจารณา iPhone / อุปกรณ์รุ่นปัจจุบันและมีมนุษย์มากขึ้น สตริงที่อ่านได้


1

นี่คือตัวอย่าง Xcode 11 Swift จากคำตอบที่ยอดเยี่ยมของHotJard ข้างต้นนี่เป็นการเพิ่มisDeviceBool และใช้SIMULATOR_UDIDแทนชื่อ การมอบหมายตัวแปรจะทำในแต่ละบรรทัดเพื่อให้คุณสามารถตรวจสอบได้ง่ายขึ้นในตัวดีบักหากคุณเลือก

import Foundation

// Extensions to UIDevice based on ProcessInfo.processInfo.environment keys
// to determine if the app is running on an actual device or the Simulator.

@objc extension UIDevice {
    static var isSimulator: Bool {
        let environment = ProcessInfo.processInfo.environment
        let isSimulator = environment["SIMULATOR_UDID"] != nil
        return isSimulator
    }

    static var isDevice: Bool {
        let environment = ProcessInfo.processInfo.environment
        let isDevice = environment["SIMULATOR_UDID"] == nil
        return isDevice
    }
}

นอกจากนี้ยังมีรายการในพจนานุกรมของซึ่งควรประกอบด้วยDTPlatformNamesimulator


0

ใช้รหัสด้านล่างนี้:

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

ทำงานเพื่อSwift 4และXcode 9.4.1



0

นอกจากคำตอบอื่น ๆ

ใน Objective-C, เพียงให้แน่ใจว่าคุณได้รวมTargetConditionals

#include <TargetConditionals.h>

TARGET_OS_SIMULATORก่อนที่จะใช้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.