Swift 베이직

Swift는 iOS, macOS, watchOS 및 tvOS 앱 개발을위한 새로운 프로그래밍 언어입니다. 그럼에도 불구하고 Swift의 많은 부분은 C 및 Objective-C로 개발 한 경험에서 친숙 하게 느껴질것 입니다.

Swift는 정수의 경우 Int, 부동 소수점 값의 경우 Double 및 Float, 부울 값의 경우 Bool, 텍스트 데이터의 경우 String을 포함하여 모든 기본 C 및 Objective-C 유형의 자체 버전을 제공합니다. Swift는 또한 Collection Types에 설명 된대로 세 가지 기본 컬렉션 유형 인 Array, Set 및 Dictionary의 강력한 버전을 제공합니다.

C와 마찬가지로 Swift는 변수를 사용하여 식별 이름으로 값을 저장하고 참조합니다. Swift는 또한 값을 변경할 수없는 변수를 광범위하게 사용합니다. 이를 상수라고하며 C의 상수보다 훨씬 강력합니다. 상수는 Swift에서 코드를 변경할 필요가없는 값으로 작업 할 때 코드를 더 안전하고 명확하게 만드는 데 사용됩니다.

익숙한 유형 외에도 Swift는 튜플과 같이 Objective-C에서 찾을 수없는 고급 유형을 도입합니다. 튜플을 사용하면 값 그룹화를 만들고 전달할 수 있습니다. 튜플을 사용하여 함수에서 여러 값을 단일 복합 값으로 반환 할 수 있습니다.

Swift는 또한 값의 없음을 처리하는 옵셔널타입을 도입했습니다. 옵셔널 타입은 “값이 있고 x와 같습니다.”또는 “값이 전혀 없습니다”라고 말합니다. 옵셔널을 사용하는 것은 Objective-C에서 포인터와 함께 nil을 사용하는 것과 비슷하지만 클래스뿐만 아니라 모든 유형에서 작동합니다. 옵셔널은 Objective-C의 nil 포인터보다 더 안전하고 표현력이 높을뿐만 아니라 Swift의 가장 강력한 기능의 핵심입니다.

Swift는 타입세이프(type-safe) 언어입니다. 즉, 코드가 작업 할 수 있는 값 유형을 명확하게 하는데 도움이됩니다. 코드의 일부에 String이 필요한 경우 타입 안전성은 실수로 Int를 전달하는 것을 방지합니다. 마찬가지로 타입 안전성은 선택적 String이 아닌 선택적 String이 필요한 코드에 실수로 선택적 String을 전달하는 것을 방지합니다. 타입 안전성은 개발 프로세스에서 가능한 한 빨리 오류를 포착하고 수정하는 데 도움이됩니다.

상수와 변수 (Constants and Variables)

상수 및 변수는 이름 (예 : maximumNumberOfLoginAttempts 또는 welcomeMessage)을 특정 유형의 값 (예 : 숫자 10 또는 문자열 “Hello”)과 연결합니다. 상수 값은 설정 한 후에는 변경할 수 없지만 변수는 나중에 다른 값으로 설정할 수 있습니다.

상수와 변수의 선언 (Declaring Constants and Variables)

상수와 변수는 사용하기 전에 선언해야합니다. let 키워드로 상수를 선언하고 var 키워드로 변수를 선언합니다. 다음은 사용자의 로그인 시도 횟수를 추적하기 위해 상수와 변수를 사용하는 방법의 예입니다.

let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0

이 코드는 다음과 같이 읽을 수 있습니다.

“maximumNumberOfLoginAttempts라는 새 상수를 선언하고 값을 10으로 지정합니다. 그런 다음 currentLoginAttempt라는 새 변수를 선언하고 초기 값을 0으로 지정합니다.”

이 예에서는 최대 값이 변경되지 않기 때문에 허용되는 최대 로그인 시도 횟수가 상수로 선언됩니다. 이 값은 로그인 시도가 실패 할 때마다 증가해야하기 때문에 현재 로그인 시도 카운터는 변수로 선언됩니다.

여러 상수 또는 여러 변수를 쉼표로 구분하여 한 줄에 선언 할 수 있습니다.

var x = 0.0, y = 0.0, z = 0.0

NOTE
코드에 저장된 값이 변경되지 않으면 항상 let 키워드를 사용하여 상수로 선언하세요. 변경할 수 있어야하는 값을 저장할 때만 변수를 사용하십시오.

타입 지정 (Type Annotations)

상수나 변수가 저장할 수있는 값의 종류를 명확히 하기 위해 상수 또는 변수를 선언 할 때 타입명을 지정 할 수 있습니다. 상수 또는 변수 이름 뒤에 콜론, 공백, 사용할 타입 이름을 차례로 배치하여 타입 어노테이션을 작성합니다.

이 예제는 변수가 문자열 값을 저장할 수 있음을 나타 내기 위해 welcomeMessage라는 변수에 대한 타입을 지정합니다.

var welcomeMessage: String

콜론 뒤의 선언은 “… 유형…”을 의미하므로 위 코드는 다음과 같이 읽을 수 있습니다.

“문자열 타입의 welcomeMessage라는 변수를 선언합니다.”

“문자열 타입”이라는 문구는 “모든 문자열 값을 저장할 수 있음”을 의미합니다. 저장할 수있는 “것의 종류”를 의미한다고 생각하십시오.

이제 welcomeMessage 변수를 오류 없이 임의의 문자열 값으로 설정할 수 있습니다.

welcomeMessage = "안녕"

최종 변수 이름 뒤에 단일 타입 어노테이션을 사용하여 쉼표로 구분 된 단일 행에 동일한 유형의 여러 관련 변수를 정의 할 수 있습니다.

var red, green, blue: Double

NOTE
실제로 타입을 지정하는 경우는 거의 없습니다. 정의 된 지점에서 상수 또는 변수의 초기 값을 제공하면 Swift는 타입 안전성 및 타입 추론에 설명 된대로 거의 항상 해당 상수 또는 변수에 사용할 타입을 추론 할 수 있습니다. 위의 welcomeMessage 예제에서는 초기 값이 제공되지 않으므로 welcomeMessage 변수의 유형은 초기 값에서 유추되는 것이 아니라 타입 어노테이션으로 지정됩니다.

상수 및 변수의 이름지정 (Naming Constants and Variables)

상수 및 변수 이름은 유니 코드 문자를 포함하여 거의 모든 문자를 포함 할 수 있습니다.

let π = 3.14159
let 안녕 = "안녕하세요"
let 🐶🐮 = "dogcow"

상수 및 변수 이름에는 공백 문자, 수학 기호, 화살표, 개인용 유니 코드 스칼라 값 또는 선 및 상자 그리기 문자가 포함될 수 없습니다. 이름의 다른 곳에 숫자가 포함될 수 있지만 숫자로 시작할 수도 없습니다.

특정 유형의 상수 또는 변수를 선언 한 후에는 동일한 이름으로 다시 선언하거나 다른 유형의 값을 저장하도록 변경할 수 없습니다. 상수를 변수로 변경하거나 변수를 상수로 변경할 수도 없습니다.

NOTE
예약 된 Swift 키워드와 동일한 이름을 상수 또는 변수에 제공해야하는 경우 이름으로 사용할 때 키워드를 백틱 (`)으로 묶으십시오. 그러나 선택의 여지가 없는 것이 아니라면 Swift 의 예약된 키워드를 이름으로 사용하지 마십시오.

기존 변수의 값을 호환 가능한 유형의 다른 값으로 변경할 수 있습니다. 이 예에서 friendlyWelcome 값은 “Hello!”에서 “Bonjour!”로 변경됩니다.

var friendlyWelcome = "Hello!"
friendlyWelcome = "Bonjour!"
// friendlyWelcome 는 Bonjour! 입니다."

변수와 달리 상수 값은 설정된 후에는 변경할 수 없습니다. 이렇게 시도하면 코드가 컴파일 될 때 오류로 보고됩니다.

let languageName = "Swift"
languageName = "Swift++"
// languageName의 값을 바꿀수 없어 컴파일 에러나 날것입니다.

상수 및 변수 프린팅 (Printing Constants and Variables)

print (_ : separator : terminator 🙂 함수를 사용하여 상수 또는 변수의 현재 값을 프린트 할 수 있습니다.

print(friendlyWelcome)
// Prints "Bonjour!"

print (_ : separator : terminator 🙂 함수는 하나 이상의 값을 적절한 출력으로 인쇄하는 전역 함수입니다. 예를 들어 Xcode에서 print (_ : separator : terminator 🙂 함수는 Xcode의 “콘솔”창에 출력을 인쇄합니다. separator 및 terminator 매개 변수에는 기본값이 있으므로이 함수를 호출 할 때 생략 할 수 있습니다. 기본적으로 이 함수는 줄 바꿈을 추가하여 프린트하는 라인을 종료합니다. 뒤에 줄 바꿈없이 값을 인쇄하려면 빈 문자열을 종결 자로 전달합니다 (예 : print (someValue, terminator : “”)). 기본값이있는 매개 변수에 대한 자세한 내용은 [기본 매개 변수 값]을 참조하십시오.

Swift는 문자열 보간(string interpolation)을 사용하여 상수 또는 변수의 이름을 문자열 중간에 \(변수)로 표시하고 Swift가 해당 상수 또는 변수의 현재 값으로 대체하도록 프롬프트합니다. 이름을 괄호로 묶고 여는 괄호 앞에 백 슬래시로 이스케이프합니다.

print("friendlyWelcome 의 현재 값은 \(friendlyWelcome) 입니다.")
// 프린트 "friendlyWelcome 의 현재 값은 Bonjour! 입니다."

주석 (Comments)

주석을 사용하여 코드에 실행할 수없는 텍스트를 메모 또는 알림으로 포함합니다. 코드가 컴파일 될 때 Swift 컴파일러는 주석을 무시합니다.

Swift의 주석은 C의 주석과 매우 유사합니다. 한 줄 주석은 두 개의 슬래시 (//)로 시작합니다.

// 이것은 주석입니다.

여러 줄 주석은 슬래시와 별표 (/*)로 시작하고 별표와 슬래시 (*/)로 끝납니다.

/* 이것 또한 주석 입니다.
그러나 두줄 이상의 주석입니다. */

C의 여러 줄 주석과 달리 Swift의 여러 줄 주석은 다른 여러 줄 주석 안에 중첩 될 수 있습니다.

/* 첫번째 멀티라인 주석입니다.
 /* 두번째 멀티라인에 포함된 주석입니다 */
첫번째 멀티라인 주석의 끝입니다. */

중첩 된 여러 줄 주석을 사용하면 코드에 이미 여러 줄 주석이 포함 된 경우에도 큰 코드 블록을 빠르고 쉽게 주석 처리 할 수 있습니다.

세미콜론 (Semicolons)

다른 많은 언어와 달리 Swift는 코드의 각 문 뒤에 세미콜론 (;)을 작성하지 않아도되지만 원하는 경우 그렇게 할 수 있습니다. 그러나 한 줄에 여러 개의 개별 문을 작성하려면 세미콜론이 필요합니다.

let cat = "🐱"; print(cat)
// Prints "🐱"

정수 (Integers)

정수는 42 및 -23과 같이 분수 구성 요소가없는 정수입니다. 정수는 부호가 있거나 (양수, 0 또는 음수) 부호가없는 (양수 또는 0) 수 입니다.

Swift는 8, 16, 32 및 64 비트 형식으로 부호있는 정수와 부호없는 정수를 제공합니다. 이러한 정수는 8 비트 부호없는 정수는 UInt8 유형이고 32 비트 부호있는 정수는 Int32 유형이라는 점에서 C와 유사한 명명 규칙을 따릅니다. Swift의 모든 유형과 마찬가지로 이러한 정수 유형에도 대문자로 시작합니다.

정수 범위
min 및 max 속성을 사용하여 각 정수 유형의 최소값과 최대 값에 액세스 할 수 있습니다.

let minValue = UInt8.min  // 타입은 UInt8 이며 최소 값은 0 입니다.
let maxValue = UInt8.max  // UInt8 타입이며 최대 값은 255 입니다.

이러한 속성의 값은 적절한 크기의 숫자 유형 (예 : 위 예의 UInt8)이므로 동일한 유형의 다른 값과 함께 표현식에서 사용할 수 있습니다.

Int
대부분의 경우 코드에서 사용할 특정 크기의 정수를 선택할 필요가 없습니다. Swift는 현재 플랫폼의 기본 단어 크기와 동일한 크기를 갖는 추가 정수 유형 Int를 제공합니다.

  • 32 비트 플랫폼에서 Int는 Int32와 크기가 같습니다.
  • 64 비트 플랫폼에서 Int는 Int64와 크기가 같습니다.

특정 크기의 정수로 작업해야하는 경우가 아니면 코드에서 정수 값에 항상 Int를 사용하십시오. 이는 코드 일관성과 상호 운용성을 지원합니다. 32 비트 플랫폼에서도 Int는 -2,147,483,648에서 2,147,483,647 사이의 값을 저장할 수 있으며 많은 정수 범위에 대해 충분히 큽니다.

UInt
Swift는 또한 현재 플랫폼의 기본 단어 크기와 동일한 크기를 갖는 부호없는 정수 유형 인 UInt를 제공합니다.

  • 32 비트 플랫폼에서 UInt는 UInt32와 같은 크기입니다.
  • 64 비트 플랫폼에서 UInt는 UInt64와 크기가 같습니다.

NOTE
UInt는 플랫폼의 기본 단어 크기와 크기가 같은 부호없는 정수 유형이 특별히 필요한 경우에만 사용합니다. 그렇지 않은 경우 저장할 값이 음수가 아닐 경우에도 Int가 선호됩니다. 정수 값에 대해 Int를 일관되게 사용하면 코드 상호 운용성을 돕고, 다른 숫자 유형간에 변환 할 필요가 없으며, 유형 안전성 및 유형 추론에 설명 된대로 정수 유형 추론과 일치합니다.

부동소수점 (Floating-Point Numbers)

부동 소수점 숫자는 3.14159, 0.1 및 -273.15와 같은 분수 구성 요소가있는 숫자입니다.

부동 소수점 형식은 정수 형식보다 훨씬 더 넓은 범위의 값을 나타낼 수 있으며 Int에 저장할 수있는 것보다 훨씬 크거나 작은 숫자를 저장할 수 있습니다. Swift는 두 가지 부호있는 부동 소수점 숫자 유형을 제공합니다.

  • Double은 64 비트 부동 소수점 숫자를 나타냅니다.
  • Float는 32 비트 부동 소수점 숫자를 나타냅니다.

NOTE
Double은 소수점 이하 15 자리의 정밀도를 갖는 반면, Float의 정밀도는 소수점 이하 6 자리까지 가능합니다. 사용할 적절한 부동 소수점 유형은 코드에서 작업해야하는 값의 특성과 범위에 따라 다릅니다. 두 유형 중 어느 것이 든 적절한 상황에서는 Double이 선호됩니다.

타입 안전성 및 타입 추론

Swift는 타입세이프(type-safe) 언어입니다. 타입세이프 언어는 코드에서 사용할 수있는 값 유형에 대해 명확하게 알려줍니다. 코드의 일부에 문자열이 필요한 경우 실수로 Int를 전달할 수 없습니다.

Swift는 타입세이프 언어이기 때문에 코드를 컴파일 할 때 타입 검사를 수행하고 일치하지 않는 유형을 오류로 보고합니다. 이를 통해 개발 프로세스에서 가능한 한 빨리 오류를 포착하고 수정할 수 있습니다.

타입 검사는 다양한 유형의 값으로 작업 할 때 오류를 방지하는 데 도움이됩니다. 그러나 선언하는 모든 상수 및 변수의 유형을 지정해야한다는 의미는 아닙니다. 필요한 값 타입을 지정하지 않으면 Swift는 타입 추론을 사용하여 적절한 유형을 찾습니다. 타입추론을 사용하면 컴파일러가 제공 한 값을 검사하기 만하면 코드를 컴파일 할 때 특정 표현식의 타입을 자동으로 추론 할 수 있습니다.

타입 추론으로 인해 Swift는 C 또는 Objective-C와 같은 언어보다 훨씬 적게 타입 선언이 가능합니다. 상수와 변수는 여전히 명시 적으로 타입을 지정할 수 있지만 대부분 타입을 지정하지 않아도 됩니다.

타입 추론은 초기 값으로 상수 또는 변수를 선언 할 때 특히 유용합니다. 이는 선언하는 지점에서 상수 또는 변수에 리터럴 값 (또는 리터럴)을 할당하여 수행되는 경우가 많습니다. (리터럴 값은 아래 예에서 42 및 3.14159와 같이 소스 코드에 직접 나타나는 값입니다.)

예를 들어 어떤 타입인지 말하지 않고 새 상수에 리터럴 값 42를 할당하면 Swift는 정수처럼 보이는 숫자로 초기화했기 때문에 상수가 Int가되기를 원한다고 추론합니다.

let meaningOfLife = 42
// meaningOfLife 의 타입은 Int 타입 라고 추론합니다.

마찬가지로 부동 소수점 리터럴에 대한 타입을 지정하지 않으면 Swift는 Double을 만들려고한다고 유추합니다.

let pi = 3.14159
// pi 는 Double 타입이라고 추론 합니다.

Swift는 부동 소수점 숫자 유형을 추론 할 때 항상 Double (Float 대신)을 선택합니다.

표현식에서 정수 및 부동 소수점 리터럴을 결합하면 컨텍스트에서 Double 유형이 유추됩니다.

let anotherPi = 3 + 0.14159
// anotherPi 또한 Double 타입으로 추론합니다.

리터럴 값 3은 그 자체로 명시적인 유형이 없으므로 Double의 적절한 출력 유형은 추가의 일부로 부동 소수점 리터럴의 존재에서 추론됩니다.

숫자 리터럴 (Numeric Literals)

정수 리터럴은 다음과 같이 작성할 수 있습니다.

  • 접두사가없는 10 진수
  • 0b 접두사가있는 이진수
  • 0o 접두사가있는 8 진수
  • 0x 접두사가있는 16 진수

이러한 정수 리터럴은 모두 10 진수 값 17을 갖습니다.

let decimalInteger = 17
let binaryInteger = 0b10001       // 17 이진(binary) 표현법
let octalInteger = 0o21           // 17 8진수(octal) 표현법
let hexadecimalInteger = 0x11     // 17 16진수(hexadecimal) 표현법

부동 소수점 리터럴은 10 진수 (접두사 없음) 또는 16 진수 (접두사 0x 포함) 일 수 있습니다. 소수점 양쪽에 항상 숫자 (또는 16 진수)가 있어야합니다. 소수 부동 소수점은 대문자 또는 소문자 e로 표시되는 선택적 지수를 가질 수도 있습니다. 16 진수 부동 소수점은 대문자 또는 소문자 p로 표시되는 지수가 있어야합니다.

exp의 지수가있는 10 진수의 경우 기본 숫자에 10exp를 곱합니다.

  • 1.25e2 의 의미는 1.25 x 102, 또는 125.0.
  • 1.25e-2 의 의미는 1.25 x 10-2, 또는 0.0125.

exp의 지수가있는 16 진수의 경우 기본 숫자에 2exp를 곱합니다.

  • 0xFp2 의 의미는 15 x 22, or 60.0.
  • 0xFp-2 의 의미는 15 x 2-2, or 3.75.

이러한 모든 부동 소수점 리터럴의 10 진수 값은 12.1875입니다.

let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0

숫자 리터럴은 쉽게 읽을 수 있도록 추가 타입을 포함 할 수 있습니다. 정수와 부동 소수점 모두 추가로 0을 채울 수 있으며 가독성을 높이기 위해 밑줄을 포함 할 수 있습니다. 두 형식 모두 리터럴의 기본 값에 영향을주지 않습니다.

let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1

숫자 타입 변환 (Numeric Type Conversion)

코드의 모든 범용 정수 상수 및 변수에 대해 Int 유형을 사용하십시오. 음수가 아닌 것이라도 마찬가지입니다. 일상적인 상황에서 기본 정수 유형을 사용한다는 것은 정수 상수와 변수가 코드에서 즉시 상호 운용 가능하며 정수 리터럴 값에 대한 추론 된 유형과 일치 함을 의미합니다.

다른 정수 유형은 외부 소스의 명시 적으로 크기가 지정된 데이터 나 성능, 메모리 사용량 또는 기타 필요한 최적화를 위해 당면한 작업에 특별히 필요한 경우에만 사용합니다. 이러한 상황에서 명시 적으로 크기가 지정된 유형을 사용하면 우발적 인 값 오버플로를 포착하고 사용중인 데이터의 특성을 암시 적으로 문서화하는 데 도움이됩니다.

정수 변환 (Integer Conversion)

정수 상수 또는 변수에 저장 할 수있는 숫자의 범위는 숫자 유형마다 다릅니다. Int8 상수 또는 변수는 -128에서 127 사이의 숫자를 저장할 수있는 반면 UInt8 상수 또는 변수는 0에서 255 사이의 숫자를 저장할 수 있습니다. 상수 또는 크기가 지정된 정수 유형의 변수에 맞지 않는 숫자는 오류로 보고됩니다. 코드가 컴파일 될 때 :

let cannotBeNegative: UInt8 = -1
// UInt8 은 음수를 저장할 수 없기 때문에 오류가 리포트 될것입니다.
let tooBig: Int8 = Int8.max + 1
// Int8의 최대 저장할 수 있는 값보다 크기 때문에 오류가 리포트 될것입니다.

각 숫자 타입은 다른 범위의 값을 저장할 수 있으므로 케이스 별로 숫자 타입 변환을 선택해야합니다. 이 옵트 인 접근 방식은 숨겨진 변환 오류를 방지하고 코드에서 타입 변환 의도를 명시 적으로 만드는 데 도움이됩니다.

특정 숫자 타입을 다른 타입으로 변환 하려면 기존 값으로 원하는 타입의 새 숫자를 초기화 합니다. 아래 예에서 상수 twoThousand는 UInt16 타입이고 상수 하나는 UInt8 타입입니다. 같은 타입이 아니기 때문에 직접 할당 할 수 없습니다. 대신 이 예제에서는 UInt16 (one)을 호출하여 값 1로 초기화 된 새 UInt16을 만들고 원본 대신이 이 값을 사용합니다.

let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)

추가된 양쪽 모두 이제 UInt16 타입이므로 할당이 허용됩니다. 출력 상수 (twoThousandAndOne)는 두 UInt16 값의 합이기 때문에 UInt16 유형으로 추론됩니다.

SomeType(초기값)은 Swift 타입 값 또는 초기 값을 전달하는 기본 초기화 방법입니다. 이면에서 UInt16에는 UInt8 값을 받아들이는 이니셜 라이저가 있으므로이 이니셜 라이저는 기존 UInt8에서 새 UInt16을 만드는 데 사용됩니다. 여기서는 어떤 다른 타입도 전달할 수 없습니다. UInt16이 이니셜 라이저를 제공하는 타입이어야합니다. 새로운 타입 (자신의 유형 정의 포함)을 허용하는 이니셜 라이저를 제공하기 위해 기존 유형을 확장하는 것은 [Extensions]에서 다룹니다.

정수 및 부동 소수점 변환 (Integer and Floating-Point Conversion)

정수 및 부동 소수점 숫자 타입 간의 변환은 명시 적으로 작성되어야합니다.

let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine
// pi 는 3.14159 와 같고 Double 타입으로 추론 됩니다.

여기서 상수 3의 값은 Double 타입의 새 값을 만드는 데 사용되므로 덧셈의 양쪽이 동일한 타입이됩니다. 이 변환이 없으면 할당이 허용되지 않습니다.

부동 소수점에서 정수로의 변환도 명시 적으로 만들어야합니다. 정수 타입은 Double 또는 Float 값으로 초기화 할 수 있습니다.

let integerPi = Int(pi)
// integerPi 는 3과 같고 Int 타입으로 추론 됩니다.

이러한 방식으로 새 정수 값을 초기화 할때는 부동 소수점 값은 항상 잘립니다. 이것은 4.75가 4가되고 -3.9가 -3이됨을 의미합니다.

NOTE
숫자 상수와 변수를 결합하는 규칙은 숫자 리터럴에 대한 규칙과 다릅니다. 숫자 리터럴에는 자체적으로 명시적인 타입이 없기 때문에 리터럴 값 3을 리터럴 값 0.14159에 직접 추가 할 수 있습니다. 해당 유형은 컴파일러가 평가하는 지점에서만 유추됩니다.

타입별칭 (Type Aliases)

타입 별칭은 기존 타입의 대체 이름을 정의합니다. typealias 키워드로 타입 별칭을 정의합니다.

타입 별칭은 외부 소스의 특정 크기의 데이터로 작업 할 때와 같이 문맥 상 더 적절한 이름으로 기존 타입을 참조하려는 경우에 유용합니다.

typealias AudioSample = UInt16

타입 알리아스를 정의하면 원래 이름을 사용할 수있는 모든 곳에서 별칭을 사용할 수 있습니다.

var maxAmplitudeFound = AudioSample.min
// maxAmplitudeFound 는 0 입니다.

여기서 AudioSample은 UInt16의 별칭으로 정의됩니다. 별칭이기 때문에 AudioSample.min에 대한 호출은 실제로 maxAmplitudeFound 변수에 대해 초기 값 0을 제공하는 UInt16.min을 호출합니다.

부울 (Booleans)

Swift에는 Bool이라는 기본 부울 타입이 있습니다. 부울 값은 true 또는 false 만 될 수 있으므로 논리 값이라고합니다. Swift는 true와 false의 두 가지 부울 상수 값을 제공합니다.

let orangesAreOrange = true
let turnipsAreDelicious = false

orangesAreOrange 및 turnipsAreDelicious의 타입은 부울 리터럴 값으로 초기화 되었기 때문에 부울로 추론되었습니다. 위의 Int 및 Double과 마찬가지로 상수 또는 변수를 만드는 즉시 true 또는 false로 설정하면 Bool로 선언 할 필요가 없습니다. 타입 추론은 타입이 이미 알려진 다른 값으로 상수 또는 변수를 초기화 할 때 Swift 코드를 더 간결하고 읽기 쉽게 만드는 데 도움이됩니다.

부울 값은 if 문과 같은 조건문으로 작업 할 때 특히 유용합니다.

if turnipsAreDelicious {
    print("맛있는 순무!")
} else {
    print("윽..순무는 끔찍해.")
}
// 출력 "윽..순무는 끔찍해."

Swift의 타입 세이프는 부울이 아닌 값이 부울로 대체되는 것을 방지합니다. 다음 예제는 컴파일 타임 오류를 보고합니다.

let i = 1
if i {
    // 이 예제는 컴파일 오류가 발생할것입니다.
}

그러나 아래의 예는 유효할 것입니다.

let i = 1
if i == 1 {
    // 이 예제는 정상적으로 컴파일 될것입니다.
}

i == 1 비교의 결과는 Bool 타입이므로이 두 번째 예제는 타입 검사를 통과합니다. i == 1과 같은 비교는 [기본 연산자]에서 설명합니다.

Swift의 다른 타입 세이프 예제와 마찬가지로 이 접근 방식은 우발적 인 오류를 방지하고 특정 코드 섹션의 의도를 항상 명확하게합니다.

튜플 (Tuples)

튜플은 여러 값을 단일 복합 값으로 그룹화합니다. 튜플 내의 값은 모든 타입이 될 수 있으며 서로 동일한 타입일 필요는 없습니다.

이 예제에서 (404, “Not Found”)는 HTTP 상태 코드를 설명하는 튜플입니다. HTTP 상태 코드는 웹 페이지를 요청할 때마다 웹 서버에서 반환하는 특수 값입니다. 존재하지 않는 웹 페이지를 요청하면 404 Not Found 상태 코드가 반환됩니다.

let http404Error = (404, "Not Found")
// http404Error 는 (Int, String)의 타입 이고 (404, "Not Found") 와 같습니다.

(404, “Not Found”) 튜플은 Int와 String을 함께 그룹화하여 HTTP 상태 코드에 두 개의 개별 값, 즉 숫자와 사람이 읽을 수있는 설명을 제공합니다. “(Int, String) 타입의 튜플“이라고 설명 할 수 있습니다.

모든 타입의 순열*임의의 수열을 서로 다른 순서로 섞는 것에서 튜플을 만들 수 있으며 원하는 만큼 다양한 타입을 포함 할 수 있습니다. 타입 (Int, Int, Int) 또는 (String, Bool) 또는 실제로 필요한 다른 순열의 튜플을 사용하는 것을 막을 수 없습니다.

튜플의 내용을 별도의 상수 또는 변수로 분해 한 다음 평소와 같이 액세스 할 수 있습니다.

let (statusCode, statusMessage) = http404Error
print("결과 코드는 \(statusCode) 입니다.")
// 출력 "결과 코드는 404 입니다."
print("결과 메세지는 \(statusMessage) 입니다.")
// Prints "결과 메세지는 Not Found 입니다."

튜플의 값 중 일부만 필요한 경우 튜플을 분해 할 때 밑줄 (_)이있는 튜플의 일부를 생략 할 수 있습니다.

let (justTheStatusCode, _) = http404Error
print("결과 코드는 \(justTheStatusCode) 입니다.")
// Prints "결과 코드는 404 입니다."

또는 0에서 시작하는 인덱스 번호를 사용하여 튜플의 개별 요소 값에 액세스할 수 있습니다.

print("상태코드는 \(http404Error.0) 입니다.")
// 출력 "상태코드는 404 입니다."
print("상태 메세지는 \(http404Error.1) 입니다.")
// 출력 "상태 메세지는 Not Found 입니다."

튜플이 정의 될 때 튜플의 개별 요소 이름을 지정할 수 있습니다.

let http200Status = (statusCode: 200, description: "OK")

튜플의 요소 이름을 지정하면 요소 이름을 사용하여 해당 요소의 값에 액세스 할 수 있습니다.

print("The status code is \(http200Status.statusCode)")
// Prints "상태코드는 200 입니다."
print("상태 메세지는 \(http200Status.description) 입니다.")
// Prints "상태 메세지는 OK 입니다."

튜플은 함수의 반환 값으로 특히 유용합니다. 웹 페이지 검색을 시도하는 함수는 페이지 검색의 성공 또는 실패를 설명하기 위해 (Int, String) 튜플 타입을 반환 할 수 있습니다. 각각 다른 타입의 두 개의 고유 한 값을 가진 튜플을 반환함으로써 함수는 단일 유형의 단일 값만 반환 할 수있는 경우보다 결과에 대한 더 유용한 정보를 제공합니다. 자세한 내용은 [반환 값이 여러 개인 함수]를 참조하십시오.

튜플은 관련 값의 단순한 그룹에 유용합니다. 복잡한 데이터 구조 생성에는 적합하지 않습니다. 데이터 구조가 더 복잡 할 가능성이 있는 경우 튜플이 아닌 클래스 또는 구조체로 모델링하십시오. 자세한 내용은 [구조 및 클래스]를 참조하십시오.

Error Handling

오류 처리를 사용하여 실행 중에 프로그램에서 발생할 수있는 오류 조건에 응답합니다.

값의 존재 또는 부재를 사용하여 함수의 성공 또는 실패를 전달할 수있는 옵셔널과 달리 오류 처리를 사용하면 실패의 근본 원인을 확인하고 필요한 경우 프로그램의 다른 부분에 오류를 전달 할 수 있습니다. .

함수에 오류 조건이 발생하면 오류가 발생합니다. 그러면 해당 함수의 호출자가 오류를 포착하고 적절하게 응답 할 수 있습니다.

func canThrowAnError() throws {
    //이 함수는 오류를 발생하거나 발생하지 않을 수 있습니다.
}

함수는 선언에 throws 키워드를 포함하여 오류가 발생할 수 있음을 나타냅니다. 오류가 발생할 수있는 함수를 호출 할 때 표현식 앞에 try 키워드를 추가합니다.

Swift는 catch 절에서 처리 할 때까지 현재 범위에서 오류를 자동으로 전파합니다.

do {
    try canThrowAnError()
    // 오류가 발생하지 않았습니다.
} catch {
    // 오류가 발생했습니다.
}

do 문은 하나 이상의 catch 절에 오류를 전파 할 수있는 새로운 범위를 만듭니다.

다음은 다양한 오류 조건에 대응하기 위해 오류 처리를 사용하는 방법의 예입니다.

func makeASandwich() throws {
    // ...
}

do {
    try makeASandwich()
    eatASandwich()
} catch SandwichError.outOfCleanDishes {
    washDishes()
} catch SandwichError.missingIngredients(let ingredients) {
    buyGroceries(ingredients)
}

이 예제에서 makeASandwich() 함수는 깨끗한 접시를 사용할 수 없거나 재료가 없는 경우 오류를 발생시킵니다. makeASandwich()는 오류를 발생시킬 수 있으므로 함수 호출은 try 표현식으로 래핑됩니다. 함수 호출을 do 문으로 래핑하면 throw되는 모든 오류가 제공된 catch 절에 전파됩니다.

오류가 발생하지 않으면 eatASandwich() 함수가 호출됩니다. 오류가 발생하고 SandwichError.outOfCleanDishes 케이스와 일치하면 washDishes() 함수가 호출됩니다. 오류가 발생하고 SandwichError.missingIngredients 케이스와 일치하면 catch 패턴에서 캡처 한 관련 [String] 값과 함께 buyGroceries (_ 🙂 함수가 호출됩니다.

오류 발생, 포착 및 전파는 [오류 처리]에서 자세히 다룹니다.

어셜션*True를 주장 및 프리컨디션*전제 조건
(Assertions and Preconditions)

어설션 및 프리컨디션은 런타임에 행해지는 검사입니다. 추가 코드를 실행하기 전에 필수 조건이 충족되는지 확인하는 데 사용합니다. 어설션 또는 프리컨디션의 부울 조건이 참으로 평가되면 코드 실행이 평소와 같이 계속됩니다. 조건이 거짓으로 평가되면 프로그램의 현재 상태가 유효하지 않다고 판단하여 코드 실행이 종료되고 앱이 종료됩니다.

어설션과 프리컨디션을 사용하여 코딩하는 동안 가정과 기대를 표현하므로 코드의 일부로 포함 할 수 있습니다. 어설션은 개발 중에 실수와 잘못된 가정을 찾는 데 도움이되고 프리컨디션은 프로덕션에서 문제를 감지하는 데 도움이됩니다.

런타임시 기대치를 확인하는 것 외에도 어설션 및 프리컨디션은 코드 내에서 유용한 문서 형식이됩니다. 위의 오류 처리에서 설명한 오류 조건과 달리 어설션 및 프리컨디션은 복구 가능하거나 예상되는 오류에 사용되지 않습니다. 실패한 어설션 또는 프리컨디션은 잘못된 프로그램 상태를 나타 내기 때문에 실패한 어설션(true 인경우)을 포착 할 방법이 없습니다.

어설션과 프리컨디션을 사용하는 것이 잘못된 조건이 발생하지 않도록 코드를 대체하는 것은 아닙니다. 그러나 이를 사용하여 유효한 데이터 및 상태를 적용하면 잘못된 상태가 발생하는 경우 앱이 더 예측 가능하게 종료되고 문제를 디버깅하기가 더 쉬워집니다. 유효하지 않은 상태가 감지되는 즉시 실행을 중지하면 유효하지 않은 상태로 인한 손상을 제한하는 데 도움이됩니다.

어설션과 프리컨디션의 차이점은 어설션은 디버그 빌드에서만 확인되지만 프리컨디션은 디버그 및 프로덕션 빌드 모두에서 확인됩니다. 프로덕션 빌드에서는 어설션 내부의 조건이 평가되지 않습니다. 즉, 프로덕션 성능에 영향을주지 않고 개발 프로세스 중에 원하는만큼 많은 어설션을 사용할 수 있습니다.

어설션으로 디버깅 (Debugging with Assertions)
Swift 표준 라이브러리에서 assert (_ : _ : file : line : ) 함수를 호출하여 어설 션을 작성합니다. 이 함수에 true 또는 false로 평가되는 표현식과 조건 결과가 false 인 경우 표시 할 메시지를 전달합니다. 예를 들면 :

let age = -3
assert(age >= 0, "사람의 나이는 0 보자 작을 수 없습니다.")
// 이 어셜션은 -3이 0보다 크지 않기 때문에 실패합니다.

이 예에서 age >= 0 이 true로 평가되면, 즉 age 값이 음수가 아닌 경우 코드 실행이 계속됩니다. 위의 코드에서와 같이 age 값이 음수이면 age >= 0 은 false로 평가되고 어설션이 실패하여 응용 프로그램이 종료됩니다.

예를 들어 조건을 산문으로 반복하는 경우와 같이 어설션 메시지를 축약 할 수 있습니다.

assert(age >= 0)

코드가 이미 조건을 확인한 경우 assertionFailure (_ : file : line : ) 함수를 사용하여 어설션이 실패했음을 나타냅니다. 예를 들면 :

if age > 10 {
    print("롤러 코스터 또는 관람차를 탈 수 있습니다.")
} else if age >= 0 {
    print("관람차를 탈 수 있습니다.")
} else {
    assertionFailure("사람 나이는 0 보다 작을 수 없습니다.")
}

전제 조건 시행 (Enforcing Preconditions)

조건이 거짓 일 가능성이 있을 때마다 프리컨디션을 사용하지만 코드가 계속 실행 되려면 반드시 참 이어야합니다. 예를 들어 프리컨디션을 사용하여 아래 첨자가 범위를 벗어나지 않았는지 확인하거나 함수에 유효한 값이 전달되었는지 확인합니다.

precondition (_ : _ : file : line : ) 함수를 호출하여 프리컨디션을 작성합니다. 이 함수에 true 또는 false로 평가되는 표현식과 조건 결과가 false 인 경우 표시 할 메시지를 전달합니다. 예를 들면 :

// 아래 첨자의 구현에서 ......
precondition(index > 0, "인덱스는 0보다 커야합니다.")

또한 preconditionFailure (_ : file : line : ) 함수를 호출하여 실패가 발생했음을 나타낼 수 있습니다. 예를 들어, 스위치의 기본 케이스가 사용되었지만 모든 유효한 입력 데이터가 스위치의 값과 다른 경우.

NOTE
선택되지 않은 모드 (-Ounchecked)에서 컴파일하면 프리컨디션이 확인되지 않습니다. 컴파일러는 프리컨디션이 항상 참이라고 가정하고 그에 따라 코드를 최적화합니다. 그러나 fatalError (_ : file : line : ) 함수는 최적화 설정에 관계없이 항상 실행을 중지합니다.프로토 타이핑 및 초기 개발 중에 fatalError (_ : file : line : ) 함수를 사용하여 fatalError ( “Unimplemented”)를 스텁 구현으로 작성하여 아직 구현되지 않은 기능에 대한 스텁을 만들 수 있습니다. fatalError는 어설션이나 프리컨디션과 달리 최적화되지 않기 때문에 스텁 구현이 발생하면 실행이 항상 중지되도록 할 수 있습니다.

에 발행했습니다
SWIFT(으)로 분류되었습니다

aaron님이 작성

아무것도 안해도 시간은 흐른다.

댓글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다