Swift: จะใช้ PREPROCESSOR Flags (เช่น "#if DEBUG`) เพื่อใช้คีย์ API ได้อย่างไร


95

ในObjective-Cบางครั้งการใช้ค่าคงที่สตริงคงที่เพื่อกำหนดคีย์ API ทางเลือก (ตัวอย่างเช่นเพื่อแยกความแตกต่างระหว่างคีย์ RELEASE และ DEBUG สำหรับแพ็คเกจการวิเคราะห์เช่น MixPanel, Flurry หรือ Crashlytics):

#if DEBUG
static NSString *const API_KEY = @"KEY_A";
#else
static NSString *const API_KEY = @"KEY_B";
#endif

แล้ว ...

[Analytics startSession:API_KEY];

สิ่งนี้แปลเป็น Swift อย่างไรเนื่องจากคอมไพเลอร์ Swift ไม่ใช้ตัวประมวลผลล่วงหน้าอีกต่อไป

คำตอบ:


161

Apple รวมการสนับสนุนแฟล็กก่อนโปรเซสเซอร์ Swift อย่างสมบูรณ์ในXcode 8ดังนั้นจึงไม่จำเป็นต้องตั้งค่าเหล่านี้ใน "อื่น ๆ Swift Flags" อีกต่อไป

การตั้งค่าใหม่นี้เรียกว่า "Active Compilation Conditions" ซึ่งให้การสนับสนุนระดับบนสุดสำหรับ Swift ที่เทียบเท่ากับแฟล็กตัวประมวลผลล่วงหน้า คุณใช้มันในลักษณะเดียวกับที่คุณทำกับ "Swift Flags อื่น ๆ " ทุกประการยกเว้นว่าไม่จำเป็นต้องนำหน้าค่าด้วย "-D" (ดังนั้นจึงสะอาดกว่าเล็กน้อย)

จากบันทึกประจำรุ่น Xcode 8 :

Active Compilation Conditionsเป็นการตั้งค่าการสร้างใหม่สำหรับการส่งผ่านแฟล็กการคอมไพล์ตามเงื่อนไขไปยังคอมไพเลอร์ Swift แต่ละองค์ประกอบของค่าของการตั้งค่านี้จะส่งผ่านไปยัง swiftc ที่ขึ้นต้นด้วย-D ในลักษณะเดียวกับที่องค์ประกอบของการPreprocessor Macrosส่งต่อเสียงดังด้วยคำนำหน้าเดียวกัน (22457329)

ป้อนคำอธิบายภาพที่นี่

คุณใช้การตั้งค่าด้านบนดังนี้:

#if DEBUG
    let accessToken = "DebugAccessToken"
#else
    let accessToken = "ProductionAccessToken"
#endif

2
หมายเหตุ: คุณไม่ควรระบุ = 1 หรืออื่น ๆ = ค่า แต่คุณต้องระบุชื่อแฟล็กเท่านั้น :]
JRG-Developer

@ JRG-Developer ฉันไม่เห็นด้วย แต่ฉันไม่แน่ใจว่าความคิดเห็นของคุณนำไปใช้ที่นี่อย่างไร
Dan Loewenherz

9
นี่เป็นคำตอบที่เป็นประโยชน์ แต่มาจากพื้นหลัง Objective-C (ตามที่ฉันคิดว่ามีนักพัฒนา iOS หลายคน) ฉันคิดว่าฉันต้องระบุ=1... เมื่อฉันทำ ดังนั้นฉันคิดว่าฉันจะแบ่งปันเรื่องน่ารู้นี้เพื่อช่วยเหลือเพื่อนคนต่อไป :] ยังไงก็ตามขอบคุณสำหรับคำตอบของคุณที่นี่!
JRG-Developer

1
@ JRG-Developer, @Dan Loewenherz ฉันได้ตั้งค่าทั้งDEBUGในActive Compilation ConditionsและDEBUG=1ในPreprocessor Macrosและการกำหนดค่านี้ใช้ไม่ได้เลย ฉันควรเอาออกDEBUG=1ไหม ?? ไม่ชัดเจนจากความเห็นข้างบน
Bhavin_m

2
@DanLoewenherz คุณพูดถูกจริงๆ ฉันได้ตั้งค่า "ดีบัก" สำหรับการกำหนดค่าการเก็บถาวรในการตั้งค่าเป้าหมายของฉันดังนั้นทุกครั้งที่เรียกใช้คำสั่ง Debug และจะไม่เรียกใช้เงื่อนไขการเผยแพร่ ใครก็ตามที่กำลังประสบปัญหาโปรดตรวจสอบเป้าหมายของคุณBuild Configurationก่อน ตรวจสอบคำตอบนี้stackoverflow.com/questions/9063100/…สำหรับข้อมูลเพิ่มเติม
Bhavin_m

131

อัปเดต: Xcode 8 รองรับสิ่งนี้โดยอัตโนมัติแล้วโปรดดูคำตอบของ @ DanLoewenherz ด้านบน

ก่อน Xcode 8 คุณยังสามารถใช้ Macros ได้ในลักษณะเดียวกัน:

#if DEBUG
let apiKey = "KEY_A"
#else
let apiKey = "KEY_B"
#endif

อย่างไรก็ตามเพื่อให้ Swift มารับคุณจะต้องตั้งค่า "ธง Swift อื่น ๆ " ในการตั้งค่าการสร้างของเป้าหมาย:

  • เปิดการตั้งค่าการสร้างสำหรับเป้าหมายของคุณ
  • ค้นหา "ธงที่รวดเร็วอื่น ๆ "
  • เพิ่มมาโครที่คุณต้องการใช้นำหน้าด้วย-Dแฟล็ก

ป้อนคำอธิบายภาพที่นี่


คุณทำให้วันของฉัน! สำหรับฉันมันใช้ไม่ได้หากไม่มี-Dคำนำหน้า
nomnom

5

เพื่อติดตามผลการสังเกตพยายามอย่าเก็บคีย์ / ความลับ api ไว้ในข้อความธรรมดาในที่เก็บ ใช้ระบบจัดการความลับเพื่อโหลดคีย์ / ความลับลงในตัวแปรสภาพแวดล้อมของผู้ใช้ มิฉะนั้นขั้นตอนที่ 1 เป็นสิ่งจำเป็นหากยอมรับได้

  1. ใส่ "ความลับ" ในไฟล์ข้อความธรรมดาด้านบนในที่เก็บที่แนบมา
  2. สร้างรายการ../set_keys.shที่มีรายการexport API_KEY_A='<plaintext_key_aef94c5l6>'(ใช้ใบเสนอราคาเดียวเพื่อป้องกันการประเมิน)
  3. เพิ่มเฟสเรียกใช้สคริปต์ที่สามารถsource ../set_keys.shและย้ายไปที่ด้านบนของคำสั่งดำเนินการ
  4. ใน Build Settings> Preprocessor Macros ให้เพิ่มเพื่อกำหนดตามความจำเป็นเช่น API_KEY_A="$API_KEY_A"

ที่รวบรวมตัวแปรสภาพแวดล้อมไว้ในการกำหนดคอมไพเลอร์ซึ่งจะใช้ในภายหลังในการเรียกใช้ clang สำหรับไฟล์ต้นทาง

โครงสร้างไดเร็กทอรีตัวอย่าง

[10:33:15] ~/code/memo yes? tree -L 2 .
.
├── Memo
│   ├── Memo
│   ├── Memo.xcodeproj
│   ├── Memo.xcworkspace
│   ├── Podfile
│   ├── Podfile.lock
│   └── Pods
└── keys

0

ในแพ็คเกจที่รวดเร็วคุณต้องทำสิ่งนี้ภายในswiftSettingsอาร์กิวเมนต์.targetในPackage.swiftไฟล์ของคุณ ใช้defineวิธีการ(เอกสารของ Apple)หรือเอกสาร Swift

targets: [
.target(name: String,
            dependencies: [Target.Dependency],
            path: String?,
            exclude: [String]?,
            sources: [String]?,,
            cSettings: [CSetting]?,
            cxxSettings: [CXXSetting]?,
            swiftSettings: [SwiftSetting]?,
            linkerSettings: [LinkerSetting]?),

หน้าตาของฉันเป็นแบบนี้และได้ผล!

            swiftSettings: [
               .define("VAPOR")
            ]

ในรหัสของฉันฉันสามารถรวบรวมตามเงื่อนไขโดยใช้สิ่งนี้:

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