В C / C ++ / Objective-C можете да определите макрос, използвайки препроцесори на компилатор. Освен това можете да включите / изключите някои части от кода, използвайки препроцесори на компилатор.
#ifdef DEBUG
// Debug-only code
#endif
Има ли подобно решение в Swift?
Отговори:
857 за отговор № 1Да, можете да го направите.
В Swift все още можете да използвате макросите на препроцесора "# if / # else / # endif" (макар и по-ограничени), според Документи на Apple, Ето един пример:
#if DEBUG
let a = 2
#else
let a = 3
#endif
Сега обаче трябва да зададете символа "DEBUG" другаде. Задайте го в секцията „Swift Compiler - Персонализирани флагове“, ред „Други Swift Flags“. Добавяте символа DEBUG с -D DEBUG
влизане.
Както обикновено, можете да зададете различна стойност, когато сте в Debug или когато сте в Release.
Тествах го в реален код и той работи; изглежда, че не се разпознава в детска площадка.
Можете да прочетете оригиналния ми пост тук.
ВАЖНА ЗАБЕЛЕЖКА: -DDEBUG=1
не работи. Само -D DEBUG
върши работа. Изглежда компилаторът игнорира флаг с конкретна стойност.
286 за отговор № 2
Както е посочено в Apple Документи
Компилаторът Swift не включва aпредпроцесорни. Вместо това се възползва от атрибутите за компилиране, изграждане на конфигурации и езикови функции, за да постигне същата функционалност. По тази причина директивите за препроцесори не се импортират в Swift.
Успях да постигна това, което исках с помощта на персонализирани конфигурации за изграждане:
- Отидете на вашия проект / изберете целта си / Настройки за изграждане / потърсете персонализирани флагове
- За избраната от вас цел задайте персонализирания си флаг, използвайки префикс -D (без бели интервали), както за отстраняване на грешки, така и за издаване
- Направете по-горе стъпки за всяка цел, която имате
Ето как проверявате целта:
#if BANANA
print("We have a banana")
#elseif MELONA
print("Melona")
#else
print("Kiwi")
#endif
Тестван с помощта на Swift 2.2
145 за отговор № 3
В много ситуации наистина нямате нужда от условно компилация; просто се нуждаете от условно поведение че можете да включите и изключите. За това можете да използвате променлива среда. Това има огромното предимство, което всъщност не трябва да прекомпилирате.
Можете да зададете променливата на средата и лесно да я включите или изключите в редактора на схеми:
Можете да извлечете променливата на средата с NSProcessInfo:
let dic = NSProcessInfo.processInfo().environment
if dic["TRIPLE"] != nil {
// ... do secret stuff here ...
}
Ето пример от реалния живот. Приложението ми работи само на устройството, тъй като използва музикалната библиотека, която не съществува в симулатора. Как тогава да правя снимки на екрана на симулатора за устройства, които не притежавам? Без тези снимки на екрана не мога да изпратя AppStore.
нуждая се фалшиви данни и a различен начин на обработка, Имам две променливи на средата: този, който при включване казва на приложението да генерира фалшиви данни от реалните данни, докато работи на моето устройство; другият, който при включване използва фалшиви данни (а не липсващата музикална библиотека), докато работи на симулатора. Включването / изключването на всеки един от тези специални режими е лесно благодарение на квадратчетата за променлива среда в редактора на схемата. А бонусът е, че не мога да ги използвам случайно в моята версия на App Store, тъй като архивирането няма променливи на средата.
119 за отговор № 4
Основна промяна на ifdef
заместване излезе с Xcode 8. т.е. използване на Активни условия за компилация.
Препоръчай на Изграждане и свързване в Xcode 8 Бележка за освобождаване.
Нови настройки за изграждане
Нова настройка: SWIFT_ACTIVE_COMPILATION_CONDITIONS
“Active Compilation Conditions” is a new build setting for passing conditional compilation flags to the Swift compiler.
Преди това трябваше да декларираме вашите условни флагчета за компилация под OTHER_SWIFT_FLAGS, като не забравяме да добавите „-D“ към настройката. Например, за условно компилиране със стойност MYFLAG:
#if MYFLAG1
// stuff 1
#elseif MYFLAG2
// stuff 2
#else
// stuff 3
#endif
Стойността, която трябва да добавите към настройката -DMYFLAG
Сега трябва само да предадем стойността MYFLAG на новата настройка. Време е да преместите всички тези условни стойности на компилация!
Моля, направете справка по-долу за повече информация за настройките на Swift Build в Xcode 8: http://www.miqu.me/blog/2016/07/31/xcode-8-new-build-settings-and-analyzer-improvements/
73 за отговор № 5
От Swift 4.1, ако всичко, от което се нуждаете, е само да проверите дали кодът е изграден с конфигурация за отстраняване на грешки или освобождаване, можете да използвате вградените функции:
_isDebugAssertConfiguration()
(важи, когато оптимизацията е настроена на-Onone
)(не се предлага на Swift 3+)_isReleaseAssertConfiguration()
(важи, когато оптимизацията е настроена на-O
)_isFastAssertConfiguration()
(важи, когато оптимизацията е настроена на-Ounchecked
)
например
func obtain() -> AbstractThing {
if _isDebugAssertConfiguration() {
return DecoratedThingWithDebugInformation(Thing())
} else {
return Thing()
}
}
В сравнение с макросите на препроцесора,
- ✓ Не е нужно да дефинирате персонализиран
-D DEBUG
флаг, за да го използвате - ~ Това всъщност е дефинирано по отношение на настройките за оптимизация, а не конфигурация за изграждане на Xcode
✗ Недокументирани, което означава, че функцията може да бъде премахната при всяка актуализация (но тя трябва да е безопасна за AppStore, тъй като оптимизаторът ще ги превърне в константи)
- тези веднъж отстранен, но изведени на публично място за липса на
@testable
атрибут, съдбата несигурна за бъдещия Суифт.
- тези веднъж отстранен, но изведени на публично място за липса на
✗ Използването на if / else винаги ще генерира предупреждение "Няма да бъде изпълнено".
72 за отговор № 6
употреба Активни условия за компилация настройка в Настройки за изграждане / Swift компилатор - Персонализирани флагове.
- Това е новата настройка за сглобяване за предаване на условни флагове за компилация към компилатора Swift.
- Прости добавяне на знамена като този:
ALPHA
,BETA
и т.н.
След това го проверете условия за съставяне като този:
#if ALPHA
//
#elseif BETA
//
#else
//
#endif
Съвет: Можете също да използвате
#if !ALPHA
и т.н.
69 за отговор № 7
Няма препроцесор Swift. (От една страна, произволното заместване на кодове нарушава безопасността на типа и паметта.)
Swift обаче включва опции за конфигуриране на време за изграждане, така че можете условно да включите код за определени платформи или стилове на изграждане или в отговор на флагове, които определяте с -D
аргументи компилатор. За разлика от C обаче, условно компилиран раздел от кода ви трябва да бъде синтактично пълен. Има раздел за това в Използване на Swift с какао и Objective-C.
Например:
#if os(iOS)
let color = UIColor.redColor()
#else
let color = NSColor.redColor()
#endif
39 за отговор № 8
Двата ми цента за Xcode 8:
а) Персонализиран флаг, използващ -D
префиксът работи добре, но ...
б) По-лесно използване:
В Xcode 8 има нов раздел: "Условия за активна компилация", вече с два реда, за отстраняване на грешки и освобождаване.
Просто добавете своето определение БЕЗ -D
.
24 за отговор № 9
isDebug Constant Въз основа на условията за активна компилация
Друго, може би по-просто решение, което все още води до булева, която можете да преминете във функции без да пипер #if
условностите във вашата кодова база е да дефинирате DEBUG
като една от целите за изграждане на вашия проект Active Compilation Conditions
и включвам следното (определям го като глобална константа):
#if DEBUG
let isDebug = true
#else
let isDebug = false
#endif
isDebug Constant Въз основа на настройките за оптимизация на компилатора
Тази концепция надгражда отговор на kennytm
Основното предимство при сравняване с kennytm "s е, че това не разчита на частни или недокументирани методи.
в Swift 4:
let isDebug: Bool = {
var isDebug = false
// function with a side effect and Bool return value that we can pass into assert()
func set(debug: Bool) -> Bool {
isDebug = debug
return isDebug
}
// assert:
// "Condition is only evaluated in playgrounds and -Onone builds."
// so isDebug is never changed to true in Release builds
assert(set(debug: true))
return isDebug
}()
В сравнение с макросите на препроцесора и отговор на kennytm,
- ✓ Не е нужно да дефинирате персонализиран
-D DEBUG
флаг, за да го използвате - ~ Това всъщност е дефинирано по отношение на настройките за оптимизация, а не конфигурация за изграждане на Xcode
✓ Документирана, което означава, че функцията ще следва нормални модели на освобождаване / премахване на API.
✓ Използване, ако / друго ще не генерира предупреждение "Няма да бъде изпълнено"
2 за отговор № 10
След настройването DEBUG=1
във вашия GCC_PREPROCESSOR_DEFINITIONS
Настройки за изграждане Предпочитам да използвам функция за извършване на тези обаждания:
func executeInProduction(_ block: () -> Void)
{
#if !DEBUG
block()
#endif
}
И след това просто включете в тази функция всеки блок, който искам да бъде пропуснат в Debug builds:
executeInProduction {
Fabric.with([Crashlytics.self]) // Compiler checks this line even in Debug
}
Предимството в сравнение с:
#if !DEBUG
Fabric.with([Crashlytics.self]) // This is not checked, may not compile in non-Debug builds
#endif
Че компилаторът проверява синтаксиса на моя код, така че съм сигурен, че синтаксисът му е правилен и се изгражда.
1 за отговор № 11
Това надгражда Джон Уилис " отговор, който разчита на твърдение, който се изпълнява само в компилациите на Debug:
func Log(_ str: String) {
assert(DebugLog(str))
}
func DebugLog(_ str: String) -> Bool {
print(str)
return true
}
Моят случай за използване е за записване на отчети за печат. Ето еталон за версията на Release на iPhone X:
let iterations = 100_000_000
let time1 = CFAbsoluteTimeGetCurrent()
for i in 0 ..< iterations {
Log ("⧉ unarchiveArray:(fileName) memoryTime:(memoryTime) count:(array.count)")
}
var time2 = CFAbsoluteTimeGetCurrent()
print ("Log: (time2-time1)" )
отпечатъци:
Log: 0.0
Изглежда, че Swift 4 напълно елиминира повикването на функцията.
0 за отговор № 12
! [В Xcode 8 и по-горе отидете да изградите настройка -> търсене на персонализирани знамена ]1
В код
#if Live
print("Live")
#else
print("debug")
#endif