source

#만약 스위프트 언어로 대체한다면,

itover 2023. 4. 27. 22:13
반응형

#만약 스위프트 언어로 대체한다면,

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작동합니다. 컴파일러가 특정 값을 가진 플래그를 무시하는 것 같습니다.

Apple 문서에 명시된 대로

Swift 컴파일러에는 전처리기가 포함되어 있지 않습니다.대신 컴파일 시간 속성, 빌드 구성 및 언어 기능을 활용하여 동일한 기능을 수행합니다.이러한 이유로 전처리기 지시어는 Swift에서 가져오지 않습니다.

맞춤형 빌드 구성을 사용하여 원하는 것을 달성했습니다.

  1. 프로젝트로 이동 / 대상 선택 / 빌드 설정 / 사용자 지정 플래그 검색
  2. 선택한 대상에 대해 디버그 및 릴리스 모두에 대해 공백 없이 -D 접두사를 사용하여 사용자 지정 플래그를 설정합니다.
  3. 모든 대상에 대해 위의 단계 수행

대상을 확인하는 방법은 다음과 같습니다.

#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

반응형