#만약 스위프트 언어로 대체한다면,
C/C++/Objective C에서는 컴파일러 전처리기를 사용하여 매크로를 정의할 수 있습니다.또한 컴파일러 프리프로세서를 사용하여 코드의 일부를 포함/제외할 수 있습니다.
#ifdef DEBUG
// Debug-only code
#endif
스위프트에도 비슷한 솔루션이 있습니까?
네, 할 수 있습니다.
Swift에서는 Apple 문서에 따라 "#if/#else/#endif" 전처리 매크로를 사용할 수 있습니다.다음은 예입니다.
#if DEBUG
let a = 2
#else
let a = 3
#endif
하지만 이제 "DEBUG" 기호를 다른 곳에 설정해야 합니다."Swift 컴파일러 - 사용자 정의 플래그" 섹션의 "기타 Swift 플래그" 행에서 설정합니다.를 DEBUG 기호와 합니다.-D DEBUG참가 신청
일반적으로 디버그 또는 릴리스에서 다른 값을 설정할 수 있습니다.
저는 그것을 실제 코드로 테스트했고 그것은 작동합니다; 하지만 그것은 놀이터에서 인식되지 않는 것 같습니다.
당신은 여기에서 저의 원래 게시물을 읽을 수 있습니다.
참고 파일: -DDEBUG=1작동하지 않습니다..-D DEBUG작동합니다. 컴파일러가 특정 값을 가진 플래그를 무시하는 것 같습니다.
Swift 컴파일러에는 전처리기가 포함되어 있지 않습니다.대신 컴파일 시간 속성, 빌드 구성 및 언어 기능을 활용하여 동일한 기능을 수행합니다.이러한 이유로 전처리기 지시어는 Swift에서 가져오지 않습니다.
맞춤형 빌드 구성을 사용하여 원하는 것을 달성했습니다.
- 프로젝트로 이동 / 대상 선택 / 빌드 설정 / 사용자 지정 플래그 검색
- 선택한 대상에 대해 디버그 및 릴리스 모두에 대해 공백 없이 -D 접두사를 사용하여 사용자 지정 플래그를 설정합니다.
- 모든 대상에 대해 위의 단계 수행
대상을 확인하는 방법은 다음과 같습니다.
#if BANANA
print("We have a banana")
#elseif MELONA
print("Melona")
#else
print("Kiwi")
#endif
Swift 2.2를 사용하여 테스트됨
대부분의 경우 조건부 컴파일이 필요하지 않습니다. 설정 및 해제할 수 있는 조건부 동작만 필요합니다.이를 위해 환경 변수를 사용할 수 있습니다.이것은 실제로 재컴파일할 필요가 없다는 큰 이점을 가지고 있습니다.
구성표 편집기에서 환경 변수를 설정하고 쉽게 설정 또는 해제할 수 있습니다.

NSProcess를 사용하여 환경 변수를 검색할 수 있습니다.정보:
let dic = NSProcessInfo.processInfo().environment
if dic["TRIPLE"] != nil {
// ... do secret stuff here ...
}
여기 실제 사례가 있습니다.내 앱은 시뮬레이터에 없는 음악 라이브러리를 사용하기 때문에 장치에서만 실행됩니다.그렇다면 소유하지 않은 장치에 대해 시뮬레이터에서 스크린샷을 찍으려면 어떻게 해야 합니까?스크린샷이 없으면 앱스토어에 제출할 수 없습니다.
저는 가짜 데이터와 그것을 처리하는 다른 방법이 필요합니다.두 가지 환경 변수가 있습니다. 하나는 전원을 켜면 앱이 내 장치에서 실행되는 동안 실제 데이터에서 가짜 데이터를 생성하도록 지시하는 것이고, 다른 하나는 전원을 켜면 시뮬레이터에서 실행되는 동안(누락된 음악 라이브러리가 아님) 가짜 데이터를 사용하는 것입니다.Scheme 편집기의 환경 변수 확인란 덕분에 각 특수 모드를 쉽게 설정/해제할 수 있습니다.또한 아카이빙에는 환경 변수가 없기 때문에 App Store 빌드에서 실수로 사용할 수 없습니다.
의 큰 ifdefXcode 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만 새 설정으로 전달하면 됩니다.조건부 컴파일 값을 모두 이동할 시간입니다!
Xcode 8의 빠른 빌드 설정 기능에 대한 자세한 내용은 아래 링크를 참조하십시오. http://www.miqu.me/blog/2016/07/31/xcode-8-new-build-settings-and-analyzer-improvements/
Swift 4.1에서 코드가 디버그 또는 릴리스 구성으로 빌드되었는지 확인하기만 하면 다음과 같은 기본 기능을 사용할 수 있습니다.
_isDebugAssertConfiguration()를 (으)로 입니다.-Onone)으로_isReleaseAssertConfiguration()(최적화가설정된 경우true임)(Swift 3+에서는 사용할 수 없음)_isFastAssertConfiguration()를 (으)로 입니다.-Ounchecked)
예.
func obtain() -> AbstractThing {
if _isDebugAssertConfiguration() {
return DecoratedThingWithDebugInformation(Thing())
} else {
return Thing()
}
}
프리프로세서 매크로와 비교하면,
- 정의를
-D DEBUG그것을 사용하기 위한 깃발 - 실제로는 Xcode 빌드 구성이 아닌 최적화 설정의 관점에서 정의됩니다.
◦ 문서화되지 않음. 즉, 모든 업데이트에서 해당 기능을 제거할 수 있습니다(그러나 옵티마이저가 이를 상수로 변환하므로 AppStore 안전해야 합니다).
- 이것들은 일단 제거되었지만, 속성이 부족하여 대중에게 다시 알려졌으며, 미래의 스위프트에 대한 운명은 불확실합니다.
◦ if/else를 사용하면 항상 "실행되지 않음" 경고가 생성됩니다.
Xcode 8 이상
빌드 설정 / Swift 컴파일러 - 사용자 지정 플래그에서 활성 컴파일 조건 설정을 사용합니다.
- 이것은 Swift 컴파일러에 조건부 컴파일 플래그를 전달하기 위한 새로운 빌드 설정입니다.
- 다음과 같은 플래그를 간단히 추가합니다.
ALPHA,BETA
그런 다음 다음과 같은 컴파일 조건으로 확인합니다.
#if ALPHA
//
#elseif BETA
//
#else
//
#endif
팁: 사할수있다니습을 할 수도 .
#if !ALPHA
Swift 프리프로세서는 없습니다. (한 가지 예로 임의 코드 대체는 유형 및 메모리 안전을 파괴합니다.)
Swift에는 시간 옵션이 또는 코드를 할 수 .-D컴파일러 인수그러나 C와는 달리 조건부로 컴파일된 코드 섹션은 구문적으로 완전해야 합니다.이것에 대한 섹션은 스위프트 위드 코코아와 오브젝티브-C에 있습니다.
예:
#if os(iOS)
let color = UIColor.redColor()
#else
let color = NSColor.redColor()
#endif
활성 컴파일 조건을 기반으로 한 isdebug 상수
할 수 또 다른,더 간단한 입니다.#if은 코베이스전조다같음습다니과은건의체드다같니를 입니다.DEBUG프로트빌대중상하나로드젝▁build▁one▁as로▁of▁target'▁your▁project나하.Active Compilation Conditions다음을 포함합니다(글로벌 상수로 정의).
#if DEBUG
let isDebug = true
#else
let isDebug = false
#endif
is 컴파일러 최적화 설정에 기반한 디버그 상수
이 개념은 케니티엠의 답변을 기반으로 합니다.
케니티엠과 비교할 때 가장 큰 장점은 이것이 개인적이거나 문서화되지 않은 방법에 의존하지 않는다는 것입니다.
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
}()
프리프로세서 매크로와 케니티엠의 답변과 비교하면,
- 정의를
-D DEBUG그것을 사용하기 위한 깃발 - 실제로는 Xcode 빌드 구성이 아닌 최적화 설정의 관점에서 정의됩니다.
◦ 문서화됨. 즉, 이 기능이 일반적인 API 릴리스/사용되지 않는 패턴을 따릅니다.
◦ if/else를 사용해도 "실행되지 않음" 경고가 생성되지 않습니다.
Xcode 8에 대한 내 2센트:
다음을 사용하는 사용자 지정 플래그-D접두사는 괜찮지만...
간편한 사용:
Xcode 8에는 디버그 및 릴리스를 위한 "활성 컴파일 조건"이라는 새로운 섹션이 있습니다.
WITH 를간추가를 사용하여 .-D.
Moignans는 여기서 대답하는 것이 좋습니다.도움이 될 경우를 대비해 다른 정보가 있습니다
#if DEBUG
let a = 2
#else
let a = 3
#endif
아래와 같이 매크로를 부정할 수 있습니다.
#if !RELEASE
let a = 2
#else
let a = 3
#endif
Xcode Version 9.4.1로 만든 Swift 프로젝트에서 Swift 4.1
#if DEBUG
#endif
프리프로세서 매크로에서 DEBUG=1이 이미 Xcode로 설정되어 있기 때문에 기본적으로 작동합니다.
따라서 DEBUG "out of box"인 경우 #을 사용할 수 있습니다.
그런데, 조건 컴파일 블록을 일반적으로 사용하는 방법은 애플의 책인 "The Swift Programming Language 4.1(Compiler Control Statement 섹션)과 컴파일 플래그 작성 방법 및 Swift의 C 매크로에 해당하는 내용은 다른 Apple의 책 Using Swift with Cocoa and Objective C 섹션(Preprocessor Directives 섹션)에 나와 있습니다.
미래에 애플이 그들의 책을 위해 더 자세한 내용과 색인을 작성하기를 바랍니다.
X코드 9 이상
#if DEVELOP
//print("Develop")
#elseif PRODUCTION
//print("Production")
#else
//
#endif
인수를 사용하는 프로세서가 있으며 아래에 나열했습니다.원하는 대로 인수를 변경할 수 있습니다.
#if os(macOS) /* Checks the target operating system */
#if canImport(UIKit) /* Check if a module presents */
#if swift(<5) /* Check the Swift version */
#if targetEnvironment(simulator) /* Check envrionments like Simulator or Catalyst */
#if compiler(<7) /* Check compiler version */
또한 다음과 같은 사용자 지정 플래그를 사용할 수 있습니다.DEBUG또는 정의한 다른 플래그
#if DEBUG
print("Debug mode")
#endif
설정 후DEBUG=1당신의GCC_PREPROCESSOR_DEFINITIONS빌드 설정 기능을 사용하여 다음과 같은 호출을 하는 것을 선호합니다.
func executeInProduction(_ block: () -> Void)
{
#if !DEBUG
block()
#endif
}
그런 다음 디버그 빌드에서 생략할 블록을 이 함수에 포함합니다.
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
컴파일러가 내 코드의 구문을 확인하여 구문이 올바르고 빌드된다는 것입니다.
![Xcode 8 이상에서는 빌드 설정으로 이동 -> 사용자 정의 플래그 검색 ]1
코드로
#if Live
print("Live")
#else
print("debug")
#endif
func inDebugBuilds(_ code: () -> Void) {
assert({ code(); return true }())
}
이는 디버그 컴파일에서만 실행되는 Assert에 의존하는 Jon Willis의 답변을 기반으로 합니다.
func Log(_ str: String) {
assert(DebugLog(str))
}
func DebugLog(_ str: String) -> Bool {
print(str)
return true
}
제 사용 사례는 인쇄 문을 기록하는 것입니다.다음은 아이폰 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
스위프트 4는 함수 호출을 완전히 제거한 것 같습니다.
매트의 답변을 위한 신속한 5 업데이트
let dic = ProcessInfo.processInfo.environment
if dic["TRIPLE"] != nil {
// ... do your secret stuff here ...
}
언급URL : https://stackoverflow.com/questions/24003291/ifdef-replacement-in-the-swift-language
'source' 카테고리의 다른 글
| sys.stdout이 터미널에 연결되어 있는지 여부를 탐지하려면 어떻게 해야 합니까? (0) | 2023.06.06 |
|---|---|
| C에 대한 공통 배열 길이 매크로? (0) | 2023.06.06 |
| 마이크로소프트.사무실. 인터럽트.Excel 참조를 찾을 수 없습니다. (0) | 2023.04.27 |
| WPF 사용자 제어의 로드된 이벤트가 두 번 이상 발생함 (0) | 2023.04.27 |
| c#에서 술어란 무엇입니까? (0) | 2023.04.27 |
