[Swift] #로 시작하는 키워드 알아보기

#if, #elseif, #else, #endif , #sourceLocation , #error, #warning , #available 살펴보기

naljin
13 min readJan 29, 2022

들어가기 전에

개-하! 제목을 #로 시작하는 키워드 알아보기라고 했지만,, 이거는 사실 저번 에 쓴 글까지 다 봐야 커버 가능한 내용입니다.. ㅎ 그 와중에 빼먹은 것도 있는건 안비밀,, 튼 적당한 제목이 생각이 안나서 일단 저렇게 지어버림 ㅇㅇ!

지난 시간에는 #file, #line# 으로 시작하는 literal 들에 대해 알아봤슴니다.

근데 저는 사실 저 부분 공부할 때 #if 같은 키워들도 같이 나올줄 알았거든여?? 그러니까 # 으로 시작하는 애들 설명이 다 한군데 묶여있을줄 알았단 말이져??!

https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html

하지만 어림 없지!!! 요 많은 것들 중에 우리가 Expressions 문서를 통해 살펴본건,, 요 정도?! 였어염

  • Special literal — #file, #fileID, #filePath, #line, #column , #function, #dsohandle
  • Playground literal — #colorLiteral, #fileLiteral, #imageLiteral

딱 봐도 많이 비어보이져? ㅎㅎ

사실 #keypath, #selectorExpressions 문서에서 각각 Key-Path String Expression 과 Selector Expression 으로 다루고 있긴한데, 오늘 제가 궁금한 부분은 아니니까 넘어가기로 하고요??

오늘은 Statements 문서에서 찾을 수 있는 # 로 시작하는 키워드들에 대해 알아볼겁니다요

  • Conditional Compilation Block — #if, #elseif, #else, #endif
  • Line Control Statement — #sourceLocation
  • Compile-Time Diagnostic Statement — #error, #warning
  • Availability Condition- #available

그럼 고고링~

Conditional Compilation Block (조건부 컴파일 블록)

Conditional Compilation Block을 사용하면 코드를 조건부로 컴파일할 수 있다고 합니다.

🤔 어떻게??

바로 #if#endif같은 컴파일러 지시어(compilation directive) 를 통해서요!!

가장 단순한 조건부 컴파일 블록은 요렇게 생겼습니다

Conditional Compilation Block 이라는 이름답게, 컴파일 시점에 조건이 true일때만 statement 가 컴파일되고 실행됩니다.

컴파일 조건으로는 true /false 가 들어갈수도 있고, 아래 표에 나열된 platform condition 중 하나가 될 수도 있습니다

바로 바로 os(iOS) / arch(i386) / targetEnvironment(simulator) 요런 식으로 () 안에 argument 를 넣어서 참/거짓 조건을 만들어주면 되는건디! 코드를 볼까여??

#if compiler(>=5)
print("Compiled with the Swift 5 compiler or later")
#endif
#if swift(>=4.2)
print("Compiled in Swift 4.2 mode or later")
#endif
#if compiler(>=5) && swift(<5)
print("Compiled with the Swift 5 compiler or later in a Swift mode earlier than 5")
#endif

여기서 조건을 더 추가하고 싶다면 #elseif#else 를 사용하면 됩니다

Line Control Statement (라인 제어 구문)

Line Control Statement을 사용하여 Swift가 진단(diagnostic) 및 디버깅 목적으로 사용하는 소스 코드의 위치를 변경할 수 있습니다

먼소리냐고여?? 저도 모르겠는데요??

저랑 비슷한 사람이 있었는지 Line Control Statements 를 애플 문서에서 읽긴했는데 언제 써야하는거임?? 이라는 질문이 있더라구여

답변은

니 전체 경력 통틀어서도 쓸 일 없을지도~ 아마 소스코드 generate 하는데 필요한 툴에 사용될텐데 튼 너는 사용할 일 없을테니 걱정 마셈 ㅇㅇ

??????????? 이런 답변을 원했던ㄱ ㅔ 아니거든?!!!

후,, 정보의 바다에서 원하는 내용들을 잘 캐내봅시다,,

우선 요 친구부터!

file path 로 들어가는 값은 #file, #fileID, #filePath 의 값을 변경하고, line number 은 #line 값을 변경한다네여

요런 #file, #fileID, #filePath, #line 이 뭔지 잘 모르겠다면 제 이전 글을 보고 오시기로 하고,, 그래서 어떻게 쓰이는건데??

일단 걍 #file 이랑 #line 을 playground에서 찍어볼게여

제 파일이랑 해당하는 line number 제대로 찍혔구여?

이제 #sourceLocation 키워드를 이용해서 파일명이랑 line 넘버를 재지정한다음 똑같이 #file 이랑 #line 을 찍어볼게여

홀뤼몰뤼,,, 제가 sourceLocation 에서 지정한대로 파일 이름이랑 기준 line 이 변경됐네여

#line이 101로 찍히는건 #sourceLocation 으로 지정한 line 의 다음 줄 부터가 해당 값으로 지정 되기 때문인가봐요 👀

그리고 file 과 line 파라미터를 받지 않는 #sourceLocation() 란 애도 있는디

얘는 설명에

소스 코드 위치를 default line 번호 및 파일 경로로 재설정합니다

라고 써있길래 저는 #sourceLocation(file:_,line:_) 을 통해 내 멋대로 설정해놓은 경로들을 다시 되돌려주는줄 알았쪄?? 애초에 쟤만 단독으로 쓰려면 에러가 나기도 하고욤

한번 찍어볼까요?

??? 제 예상은 myplay.playground17 이 다시 찍히는거였는데, 왜 냅다 var/folders/k1/6kbxtts16gq6pyl2wc386gpc0000gn/T/playground33-f556c0..swift27 이 찍혀버리는,,?

광기의 한국인,, 집착의 한국인,, 저 경로로 들어가본다,,

응??? 제가 playground 를 열고 작성한건 11번째 라인에 있는 import UIKit 부터거든여?? 근데 playground 생성할 때 저도 모르는 사이에 자동으로 생기는 라인들이 있었네여??

여기서 자동으로 생성된 코드들 중 마지막 라인인 10번째 라인을 볼게요

#sourceLocation(file: “myplay.playground”, line: 1)

응,,?? sourceLocation,,??????? 너가 왜 여기서 나와,,????

와 이 코드 때문에 처음 playground 에서 단순히 #file 이랑 #line 을 찍었을때 myplay.playground 와 line number 가 9 로 나왔던건가봐요;;

아까는 myplay.playground9 을 보고 “파일이랑 해당하는 line number 제대로 찍혔구여?” 라고 했었지만 사실은 sourceLocation 의 농간에 놀아나버렸던거임;;

찐 file과 line 값은 #sourceLocation() 으로 소스 코드 위치를 default line 번호 및 파일 경로로 재설정했을때 찍힌 값들이었던것이져,, 홀뤼~

오키 그러면 다시 정의를 살펴 봤을 때

#sourceLocation(file:_,line:_)#file#line 번호 customize 가능

#sourceLocation() — 소스 코드 위치를 default line 번호 및 파일 경로로 재설정

이제 설명 봐도 뭔지 ㅇㅣ해 완료!

Compile-Time Diagnostic Statement (컴파일 타임 진단 구문)

컴파일 타임 진단 구문은 컴파일 중에 오류나 경고를 발생시킵니다.

우선 #error 같은 경우에는 fatal error로 오류 메시지를 내보내고 컴파일 프로세스를 종료합니다.

#warning 은 nonfatal warning 으로 경고 메시지를 표시하며 컴파일을 진행할 수 있습니다.

안에 들어가는 메시지는 static string literal로 작성합니다. 따라서 문자열 보간이나 연결과 같은 기능을 사용할 수 없습니다. 그러나 여러 줄로 된 문자열은 사용할 수 있습니다.

예시를 보면 뭔 말인지 바로 이해 될걸여?

오키? 오키!

Availability Condition (가용성 조건)

#available 키워드로 시작하는 이 조건은 () 안에 플랫폼 이름과 버전이 들어갑니다.

if #available(iOS 11.0, *) { }

이는 즉, 현재 실행 환경 버전이 iOS 11.0 이상인지를 확인하는건데요!

🤔 ?? 나는 iOS 11.0 만 명시했는데, “그 이상” 인지를 확인하는거라고??

바로 마지막에 필수로 들어가는 인자인 * 가 해당 버전 이상인지를 체크하는 역할을 합니다.

iOS, macOS, watchOS, tvOS 등 다양한 플랫폼의 이름과 대응하는 version number를 짝지어서 추가할 수 있어요!

if #available(iOS 11.0, macOS 10.12, *) { }

이렇게 if, while, guard 문의 조건으로 들어가는 #available 을 통해서 사용할 API가 runtime에 사용 가능한지를 체크하고 실행합니다

먼 말이냐면! 현재 제 프로젝트의 iOS Deployment Target 은 14.1 이에여

근데 여기서 iOS 15.0 부터 사용할 수 있는 data(for:delegate:) 함수를 사용한다??

응 어림없어~

이건 iOS 15.0 이상에서 쓸 수 있는거셈 ㅇㅇ 하고 바로 에러 뱉어버리는디요 친절하게 이 에러를 해결할 수 있는 몇가지 방법을 제시해주네여

첫번째는 if #available 로 버전 체크한 다음에 data(for:deleagate)를 사용하셈

두세번째는 @available 붙여서 data(for:deleagate)를 포함하고 있는 함수나 클래스 자체를 iOS 15 이상에서만 호출 할 수 있게 하셈

이라는 건데 저희가 알아보고 싶은건 첫번째니까 저걸 클릭해볼게여

짜쟌 에러가 없어졌습니다. #available 을 통해서 사용할 API가 runtime에 사용 가능한지를 체크하고 실행한다는 뜻이 이제 뭔지 와닿으시나여?? 15 미만 버전을 위해서는 else 쪽에서 처리해주면 되겠져~~

그리고 availability condition 은 &&|| 같은 논리 연산자를 사용해서 결합할 수 없습니다

요런게 안된다는 말이겠져?

마무리

좋아여 오늘은 # 로 시작하는 swift 의 키워드 중 Statements 문서에 나와있는 것들을 살펴봤는데여!

  • Conditional Compilation Block — #if, #elseif, #else, #endif
  • Line Control Statement — #sourceLocation
  • Compile-Time Diagnostic Statement — #error, #warning
  • Availability Condition- #available

이제 저번 시간에 살펴본 내용들과 합치면 (from Expresions 문서)

  • Special literal — #file, #fileID, #filePath, #line, #column , #function, #dsohandle
  • Playground literal — #colorLiteral, #fileLiteral, #imageLiteral

대충 # 로 시작하는 swift 의 키워드들은 거의 살펴본 것 같습니다?!

https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html

그럼 이쯤에서 마무리하는 것으로 하며,,, 모두들 해피 설날~~!!!!!

출처

--

--

Responses (1)