Swift: làm thế nào để sử dụng Cờ trình xử lý trước (như `#if GỠ NỢ`) để triển khai các khóa API?


95

Trong Objective-Cđó, đôi khi hữu ích khi sử dụng hằng số chuỗi tĩnh để xác định các khóa API thay thế (ví dụ: để phân biệt giữa khóa RELEASE và DEBUG cho các gói phân tích, như MixPanel, Flurry hoặc Crashlytics):

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

và sau đó...

[Analytics startSession:API_KEY];

Làm thế nào để điều này dịch sang Swift, vì trình biên dịch Swift không còn sử dụng bộ tiền xử lý nữa?

Câu trả lời:


161

Apple đã bao gồm hỗ trợ đầy đủ cho các cờ tiền xử lý Swift kể từ Xcode 8 , vì vậy không còn cần thiết phải đặt các giá trị này trong "Cờ Swift khác".

Cài đặt mới được gọi là "Điều kiện biên dịch tích cực", cung cấp hỗ trợ cấp cao nhất cho cờ bộ tiền xử lý tương đương với Swift. Bạn sử dụng nó theo cách giống hệt như cách bạn sử dụng "Các cờ Swift khác", ngoại trừ việc không cần thêm giá trị bằng "-D" (vì vậy nó chỉ gọn gàng hơn một chút).

Từ ghi chú phát hành Xcode 8 :

Active Compilation Conditionslà một cài đặt xây dựng mới để chuyển các cờ biên dịch có điều kiện sang trình biên dịch Swift. Mỗi phần tử của giá trị của cài đặt này chuyển đến swiftc có tiền tố là -D, giống như cách mà các phần tử Preprocessor Macroschuyển sang clang có cùng tiền tố. (22457329)

nhập mô tả hình ảnh ở đây

Bạn sử dụng cài đặt trên như vậy:

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

2
Lưu ý: bạn không nên chỉ định = 1 hoặc bất kỳ giá trị = nào khác. Thay vào đó, bạn cần chỉ định tên cờ. :]
JRG-Developer

@ JRG-Developer Tôi không đồng ý, nhưng tôi không chắc cách bình luận của bạn áp dụng ở đây.
Dan Loewenherz

9
Đây là một câu trả lời hữu ích, nhưng đến từ nền tảng Objective-C (như tôi tưởng tượng của nhiều nhà phát triển iOS), tôi cho rằng tôi cần chỉ định =1... Tôi đã mất một chút thời gian để tìm hiểu lý do tại sao nó không hoạt động khi tôi đã làm. Vì vậy, tôi nghĩ tôi sẽ chia sẻ mẩu tin này để giúp đỡ những người bạn tiếp theo. :] Dù sao, cảm ơn câu trả lời của bạn ở đây!
JRG-Developer

1
@ JRG-Developer, @ Dan Loewenherz tôi đã đặt cả DEBUGtrong Active Compilation ConditionsDEBUG=1trong Preprocessor Macrosvà cấu hình này không làm việc ở tất cả. Tôi có nên loại bỏ DEBUG=1?? Không rõ ràng từ các ý kiến ​​trên.
Bhavin_m

2
@DanLoewenherz Bạn hoàn toàn đúng. Tôi đã đặt "Gỡ lỗi" cho cấu hình lưu trữ trong cài đặt mục tiêu của mình, vì vậy mỗi khi nó chạy câu lệnh Gỡ lỗi và không bao giờ chạy điều kiện phát hành. Bất kỳ ai đang gặp phải vấn đề thì hãy kiểm tra mục tiêu của bạn Build Configurationtrước. Kiểm tra câu trả lời này stackoverflow.com/questions/9063100/… để biết thêm thông tin.
Bhavin_m

131

CẬP NHẬT: Xcode 8 hiện hỗ trợ tính năng này tự động, hãy xem phản hồi của @ DanLoewenherz ở trên.

Trước Xcode 8, bạn vẫn có thể sử dụng Macro theo cách tương tự:

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

Tuy nhiên, để Swift chọn chúng, bạn cần đặt "Cờ Swift khác" trong Cài đặt bản dựng của mục tiêu:

  • Mở Cài đặt bản dựng cho mục tiêu của bạn
  • Tìm kiếm "cờ nhanh khác"
  • Thêm các macro bạn muốn sử dụng, đặt trước -Dcờ

nhập mô tả hình ảnh ở đây


bạn đã làm nên ngày của tôi! đối với tôi Nó không hoạt động nếu không có -Dtiền tố
nomnom

5

Như một quan sát tiếp theo, cố gắng không giữ các khóa / bí mật api ở dạng bản rõ trong kho lưu trữ. Sử dụng hệ thống quản lý bí mật để tải khóa / bí mật vào các biến môi trường của người dùng. Nếu không thì bước 1 là cần thiết.

  1. Đặt "bí mật" trong tệp văn bản rõ ở trên trong kho lưu trữ kèm theo
  2. Tạo một ../set_keys.shdanh sách có chứa một danh sách export API_KEY_A='<plaintext_key_aef94c5l6>'(sử dụng một trích dẫn duy nhất để ngăn đánh giá)
  3. Thêm giai đoạn Run script có thể source ../set_keys.shvà chuyển nó lên đầu thứ tự thực thi
  4. Trong Cài đặt bản dựng> Macro tiền xử lý, thêm vào các định nghĩa nếu cần, chẳng hạn như API_KEY_A="$API_KEY_A"

Điều đó bắt biến môi trường vào định nghĩa của trình biên dịch mà sau này được sử dụng trong mỗi lệnh gọi clang cho mỗi tệp nguồn.

Cấu trúc thư mục mẫu

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

0

Trong các gói nhanh, bạn phải thực hiện việc này bên trong swiftSettingsđối số .targettrong Package.swifttệp của mình . Sử dụng definephương pháp (tài liệu Apple) hoặc tài liệu Swift

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

Của tôi trông như thế này và nó hoạt động!

            swiftSettings: [
               .define("VAPOR")
            ]

trong mã của tôi, tôi có thể biên dịch có điều kiện bằng cách sử dụng:

#if VAPOR
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.