Search

[Swift 공식 문서] 1. The Basics

핵심 요약

Swift 는 Type Safe 한 언어. → 타입 세이프티 체크 기능이, 다른 타입의 값을 변수에 할당하려 한다면 미리 발견하고 알려준다.
변수는 콤마로 구분해 한 Line 에 선언 가능하다.
일단 let 으로 선언하고 변수의 값이 변경될 일 생기면 var 로 변경하는 습관들이기
세미콜론 ; → 줄바꿈
Int 형 리터럴에 언더스코어 _
튜플의 타입은 (타입, 타입) 으로 나타낸다.
튜플은 순회가능하다. (타입이 달라도)

The Basics

Swift는 C와 Objective-C 과 많은 부분이 유사한 언어로, Swift 를 사용하면서 이러한점을 쉽게 느낄 수 있습니다.
Swift 의 특징은 아래와 같습니다.
Swift 는 C와 Objective-C 에서 제공하는 기초적인 자료형들 Int , Double, Float, Bool, String 을 제공합니다.
Swift 는 또한 강력한 버전의 3가지 주요 collection type 을 제공합니다. Array, Set, Dictionary
강력한 Constant 기능을 가지고 있습니다.
변경할 필요가 없는 값을 다룰 때에 더 코드를 안전하게 사용할 수 있습니다.
" Optianal type "을 제공합니다
값이 존재하지 않는 상황을 handling 할 수 있도록 하는 optinal type 을 제공합니다. optional 타입이 가질 수 있는 의미는 아래와 같습니다.
값이 존재하며, 그 값이 ~ 와 같음
값이 존재하지 않음
Objectvie-C 에서 nil pointer 을 사용하는 것과 유사하지만, optional type 은
class 뿐만 아니라 모든 타입에 적용이 가능하며 더 안전합니다.
Swift 는 " type-safe 언어 " 입니다.
만약 String 타입의 변수에 Int 타입의 값을 passing 하려 한다면, type safety 가 이를 방지합니다. 마찬가지로 non-optional 타입을 요구하는 코드에 optional 타입을 passing 하려한다면 마찬가지로 type safety 가 이를 발견(catch) 하여 개발 프로세스 중 가능한 빨리 에러를 고칠 수 있도록 합니다.

Constant and Variables

self check
Constant(상수) 와 variable(변수)은 사용되기 전에 반드시 선언되어야 합니다.
let : Constant
var : Variable
let maximumNumberOfLoginAttempts = 10 var currentLoginAttempt = 0
Swift
복사
maximumNumberOfLoginAttempts 라는 constant를 선언하고 10 의 값을 할당하였습니다.
currentLoginAttempt 라는 variable 을 선언한후 0 의값을 할당하였습니다.
이 예시에서 최대 로그인 횟수는 변경되지 않는 값이므로 let 을 이용해 constant 로 선언하였고, 현재 로그인 시도 횟수는 로그인 시도에 따라 변경되는 값이므로 var 키워드를 이용해 variable 로 선언되었습니다.
여러개의 constant 와 variable 을 콤마로 구분해 한 line 에 선언할 수 있습니다.
var x = 0.0, y = 0.0, z = 0.0
Swift
복사
변경되지 않는 값을 변수로 설정하지 마세요. 저장할 값의 변경여부를 짐작할 수 없다면 일단 let 키워드로 constant 로 선언한 뒤, 값이 수정될 필요가 있다면 차후에 var 키워드로 변경합니다.

Type Annotations

constant 와 variable 을 선얼할 때 , type annotation 명시할 수 있습니다. type annotation 을 사용함으로써, 저장되 값의 종류를 명확히 할 수 있습니다. : 콜론 이후에 한칸 띄고 사용할 type 의 이름을 명시합니다.
var welcomeMessage: String
Swift
복사
한번에 여러개의 변수를 콤마로 구분하여 같은 타입으로 정의할 수 있습니다.
var red, green, blue: Double
Swift
복사
실전에서는 type annotation 을 자주 사용하지 않습니다. 초기값과 함께 constant 또는 variable 을 정의할경우, Swift 는 초기값을 이용해 변수의 type 을 추론하기 때문입니다. 자세한 사항은 아래의 Type Safety and Type Inference part에서 확인하세요.

Naming Constants and Variables

Constat 와 variable 의 이름은 모든 character(문자) 를 사용할 수 있으며, Unicode 문자도 여기에 포함됩니다.
let π = 3.141592 let 你好 = "你好世界" let 🐶🐮 = "dogcow"
Swift
복사
constant 와 variable 은 아래와 같은 문자들을 이름으로 가질 수 없습니다.
whitespace characters
mathematical symbols
arrows
private-use Unicode scalar values
line- and box-drawing characters.
constant 와 variable 의 이름은 숫자로 시작할 수 없습니다
한번 constant 와 variable 을 특정한 타입으로 선언했다면, 같은 이름으로 재선언이 불가하며, 다른 타입의 값을 저장하도록 변경할 수 없습니다. constant 를 variable 로 변경할 수 없고 variable 을 constant 로 변경할 수도 없습니다.
Swift 의 예약어와 같은 이름의 constant 또는 variable 이 필요하다면 , 그 키워드를 으로 감싸십시오. 그러나 이러한 키워드의 사용은 가능한 피해야합니다.
variable 에 저장된 값은 호환가능한 타입의 다른 값으로 변경이 가능합니다.
var friendlyWelcome = "Hello!" friendlyWelcome = "Bonjour!" // friendlyWelcome is now "Bonjour!"
Swift
복사
Constant 는 값의 변경이 불가능합니다.
let languageName = "Swift" languageName = "Swift++" // This is a compile-time error: languageName cannot be changed.
Swift
복사

Printing Constants and Variables

print(_:separator:terminator:) 함수를 이용해 constant 와 variable 의 현재 값을 출력할 수 있습니다.
print(friendlyWelcome) // Prints "Bonjour!"
Swift
복사
print(_:separator:terminator:) 은 global 함수로, 하나 또는 여러개의 값을 적절한 output 으로 출력합니다.
예를 들어,
print(_:separator:terminator:) 함수는 Xcode 의 "console" pane 에 결과를 출력합니다. seperator 와 terminator 파라미터는 초기값이 존재하기 때문에, 생략 가능합니다. 기본적으로 줄을 바꿈으로써 한줄의 출력을 종료합니다. 줄바꿈 없이 값을 출력하고 싶다면 terminator 에 빈 문자열을 전달하면 됩니다. - 예를들어 print(someValue, terminator: "") 이러한 파라미터의 초기값에 대한 더 많은 정보는 다음 문서를 참고하세요 Default Parameter Values.
Swift 는 string interpolation 을 사용해서 constant 또는 variable 의 이름을 placeholder 로서 더 긴 String 에 포함시킬 수 잇습니다. 그리고 Swift 에게 constant 와 variable 의 현재 값으로 placeholder 을 대체하도록 유도할 수 있습니다. 변수의 이름을 괄호로 감싸고 앞에 백슬래시를 작성하세요
print("The current value of friendlyWelcome is \(friendlyWelcome)") // Prints "The current value of friendlyWelcome is Bonjour!"
Swift
복사
All options you can use with string interpolation are described in String Interpolation.

Comments

주석을을 활용하여 코드에 실행되지 않는 텍스트를 포함시킬 수 있습니다. 주석을 활용해 메모를 작성할 수 있습니다. Comment 는 컴파일 될 때, Swift 컴파일러에 의해 무시됩니다. 따라서 실행파일의 크기에 이러한 주석들은 포함되지 않습니다.
Swift 의 Comment 들은 C의 주석과 매우 유사합니다.
한줄짜리 주석은 슬래시 두개로 시작합니다
// This is a comment.
Swift
복사
여러줄의 주석은 /* */ 으로 감싸줍니다.
/* This is also a comment but is written over multiple lines. */
Swift
복사
C의 multiline 주석과는 다르게, Swift는 다른 주석안에 주석을 감쌀수 있습니다.
이러한 Nested multiline comment 는 주석이 포함되어 있는 코드블럭을 쉽게 주석으로 만들 수 있게 해주고, 또 그 반대도 쉽게 만들어줍니다.

Semicolons

다른 언어와는 다르게 Swift 는 각코드의 끝에 semicolon 을 작성할 필요가 없습니다.
하지만 semicolon 을 활용해 한줄에 여러개의 code statement 를 작성할 수 있습니다.
let cat = "🐱"; print(cat) // Prints "🐱"
Swift
복사

Integers

Swift 는 signed(부호를 가지는 값, 양수 음수의 구별) 또는 unsigned(부호를 가지지 않는 값, 오직 양수) integers in 8,16, 32 그리고 64 bit 의 형태로 제공합니다. 이러한 integers 는 C와 유사한 이름을가집니다. 8-bit unsigned integers 는 UInt8 signed 32-bit 타입은 Int32 여타 다른 타입과도 유사하게 Intergers 의 타입 이름은 대문자로 시작합니다.

Integer Bounds

각각의 integer min , max 프로퍼티를 통해 각각의 integer 타입의 최대 최소값에 접근할 수 있습니다.
let minValue = UInt8.min // minValue is equal to 0, and is of type UInt8 let maxValue = UInt8.max // maxValue is equal to 255, and is of type UInt8
Swift
복사
이러한 프로퍼티의 리턴 값은 적절한 크기의 number type 입니다. (위 예시에서는 UInt8 타입)따라서 이러한 표현은 같은 타입의 다른 값 과 함께 사용될 수 있습니다.

Int

대부분의 경우에서 integer 의 구체적읜 size 를 고를 필요가 없습니다. Swift 는 추가적인 integer 타입인 Int 타입을 제공합니다. 이 타입은 현재 플랫폼의 native word size 와 같은 트기를 가집니다.
On a 32-bit platform, Int is the same size as Int32.
On a 64-bit platform, Int is the same size as Int64.
구체적인 크기의 integer 가 필요한 것이 아니라면 항상 Int 타입을 이용하여 integer 값을 표현하시오. 이 타입은 코드의 일관성과 호환성을 제공합니다. 심지어 32- bit 플랫폼에서 조차 Int 2,147,483,648 와 2,147,483,647 사이의 모든 값을 저장할 수 있으며, 이 값은 많은 integer 범위에 대해 충분히 큽니다.

UInt

Swift 는 또한 현재 플랫폼의 word size 와 같은 사이즈를 가지는 unsigned integer 타입인 UInt 를 제공합니다.
On a 32-bit platform, UInt is the same size as UInt32.
On a 64-bit platform, UInt is the same size as UInt64.
UInt 는 플랫폼의 native word size 와 같은 크기의 unsigned integer 타입이 필요한 경우에만 사용하세요. 음수가 아닌 값이 저장된다고 해도 되도록이면 Int 타입을 사용하세요. Int 타입의 일관된 사용은 코드의 상호호환성을 높이고, 다른 수의 타입들간의 변환을 피할 수 있으며, integer 타입 추론에 알맞습니다. 더 자세한 사항은 다음 문서를 참고하세요 Type Safety and Type Inference.

Floating-Point Numbers

Floating-point numbers 란 fractional component( 소수 부분 ) 을 가지는 숫자들을 의미합니다.
Floating-point 타입은 정수 타입보다 더 넓은 범위의 수를 나타날 수 잇습니다. 또한 Int 형보다 더 크거나 작은 수를 저장할 수 있습니다. Swift 는 두개의 signed floating-point number 타입을 제공합니다.
Double : 64 비트 실수
Float : 32 비트 실수
은 적어도 15자리의 10진수의 정확한 표현이 가능합니다. 반면에 Float 형은 6자리의 10진수로 표현이 가능합니다. 코드에서 사용하고자 하는 floating -type 의 크기를 고려해서 이 변수들을 사용하세요. 두 타입이 모두 적당한 상황에서는 Double 을 사용하세요

Type Safety and Type Inference

Swift 는 type-safe 언어입니다. type safe 언어는 코드에서 사용되는 값의 자료형을 명확히 해야합니다. String 타입의 코드에 Int 형을 전달할 수 없습니다.
Swift 의 type safe 덕분에, 컴파일링 시 모든 타입을 점검해서 잘못 할당된 타입들을 error 로 표시해줍니다. 개발 과정에 있어서 이러한 에러들을 빠르게 catch 할 수 있도록 해줍니다.
Type-checking 은 다른 타입의 값을 다룰 때 에러를 피할 수 있게 도와줍니다. 그러나, constant 와 variable 의 모든 타입을 구체화 해야하는 것은 아닙니다. 만약 필요한 값의 타입을 명시하지 않았다면, Swift 는 타입추론을 통해 적절한 타입을 찾아냅니다. 타입 추론은 컴파일러가 변수의 값을 조사함으로써 특정 표현의 타입을 추론합니다.
타입 추론은 초기값과 함께 constant 와 variable 을 선언할 때 유용합니다. Literal 값을 constant 와 variable 에 할당함으로써 초기값을 통한 타입추론 기능을 사용할 수 잇습니다.
리터럴이란 소스코드에 직접적으로 나타나는 값들을 의미합니다.such as 42 and 3.14159
예를 들어, 리터럴 값 42 를 타입 명시 없이 할당한다면 Swift는 constant 가 Int 형 인 것으로 추론합ㄴ디ㅏ. dlsms 정수형처럼 보이는 수와 함께 constant 를 초기화 했기 때문입니다.
let meaningOfLife = 42 // meaningOfLife is inferred to be of type Int
Swift
복사
마찬가지로 float 형으로 보이는 리터럴 값을 할당시 float 으로 타입추론합니다
만약 정수형과 실수형 리터럴을 결합해서 표현한다면, 타입은 Double 형으로 추론됩니다.
let anotherPi = 3 + 0.14159 // anotherPi is also inferred to be of type Double
Swift
복사
리터럴 값인 3 자체는 어떠한 외적인 타입을 가지지 않습니다. 실수형 리터럴 부분이 추가로 존재하기 때문에 Double 인 것으로 추론됩니다.

Numeric Literals

정수형 리터럴들은 아래와 같이 적을 수 있습니다.
십진수 : 접두사 없음
이진수 : 접두사 0b
8진수 : 접두사 0o
16진수 : 접두사 0x
let decimalInteger = 17 let binaryInteger = 0b10001 // 17 in binary notation let octalInteger = 0o21 // 17 in octal notation let hexadecimalInteger = 0x11 // 17 in hexadecimal notation
Swift
복사
실수형 리터럴들은
십진수 : 접두사 없음
16진수 : 접두사 0x
항상 소수점 양쪽 모두 수가 존재해야합니다. 10진수 실수형은 또한 선택적인 지수를 가질 수 있는데, 이는 대문자 또는 소문자 e 입니다. 16진수 실수형들은 p 지수를 반드시 가져야합니다.
1.25e2 는 1.25 x 10210^{2} 또는 125.0 을 의미합니다
1.25e-2 는 1.25 x 10210^{-2} 또는 0.0125 를 의미합니다.
16진수 exp 라는 지수를 가진다면, '밑' 에는 2exp2^{exp} 가 곱해집니다.
0xFp2 는 15 x 222^{2} 또는 60.0 을 의미합니다.
0xFp-2 는 15 x 222^{-2} 또는 3.75 를 의미합니다.
아래의 모든 실수형 리터럴들은 12.1875 값을 가집니다.
let decimalDouble = 12.1875 let exponentDouble = 1.21875e1 let hexadecimalDouble = 0xC.3p0
Swift
복사
숫자 리터럴은 여분의 형식을 통해 가독성을 높일 수 있습니다. 정수형과 실수형 모두 여분의 0 들로 둘러 쌓일 수 있으며, _ (underscore) 를 포함시켜 가독성을 높일 수 있습니다. 이러한 여분의 형식에 의해서는 타입이 변경되지 않습니다.
let paddedDouble = 000123.456 let oneMillion = 1_000_000 let justOverOneMillion = 1_000_000.000_000_1
Swift
복사

Numeric Type Conversion

일반적인 목적의 정수형 constant 에는 Int 형을 사용하세요. (음수 값이 저장될리 없다고 해도)
기본적인 정수형 타입을 사용하는 것은 정수형 constant 와 variable 들이 즉시 상호 호환이 가능하다는 것을 의미하며, 리터럴 값에 대한 타입추론과도 일치하게 됩니다.
다른 정수형 타입들은 구체적으로 필요한 상황에서만 사용하세요. 외부 소스로 부터의 명시된 크기의 데이터에나 ,퍼포먼스, 메모리 사용, 다른 반드시 필요한 최적화를 해야하는 상황이 이러한 상황들의 예시입니다.
명시적으로 고정된 크기의 데이터 타입을 사용해서 값의 overflow 나, 사용되는 데이터의 본질을 명시적으로 선언하세요.

Integer Conversion

정수형 constant 또는 variable 에 저장될 수 있는 수의 범위는 각각의 type 에 따라 달라집니다. Int8 constant 또는 variable 은 -128 ~ 127 사이의 수를 저장할 수 있는 반면에 UInt8 타입은 0과 255 사이의 수를 저장할 수 있습니다. constant 또는 variable 의 정수타입 크기에 맞지 않는 수는 컴파일시 에러로 표시합니다.
let cannotBeNegative: UInt8 = -1 // UInt8 can't store negative numbers, and so this will report an error let tooBig: Int8 = Int8.max + 1 // Int8 can't store a number larger than its maximum value, // and so this will also report an error
Swift
복사
각각의 numeric 타입은 다양한 범위의 값들을 저장할 수 있기 때문에, type 을 상황에 따라 알맞게 변환 및 선택해야합니다. 이러한 접근 방식에 의해 숨겨진 변환오류를 방지하고 유형 변환의 의도를 코드에 명시할 수 있습니다.
numeric 타입을 변환하기 위해서는, 원하는 타입의 새로운 숫자를 존재하는 값과 함께 초기화 해주어야합니다. 아래의 예시에서 constant twoThousandUInt16 인 반면, constant oneUInt8 형입니다. 이 둘은 같은 타입이 아니기 때문에, 직접적으로 서로 더해질 수 없습니다. 대신, 이러한 예시들은 UInt16() 을 호출함으로써 새로운 UInt16 을 초기화 할 수 있습니다. 이 값은 원래 있던 그위치 그자리에서 사용이 가능합니다.
let twoThousand: UInt16 = 2_000 let one: UInt8 = 1 let twoThousandAndOne = twoThousand + UInt16(one)
Swift
복사
덧셈 기호의 양쪽이 모두 UInt16 형이므로, 둘의 덧셈이 가능합니다. 결과 constant 인 twoThousandAndOne 는 두개의 UInt16 형의 합이기 때문에 UInt16 형으로 추론됩니다.
SomeType(ofInitialValue) 는 Swift type 의 initializer 를 호출하는 기본적인 장법이며, 초기값을 전달합니다. 코드의 뒤편에서는, UInt16 은 initializer 가 UInt8 형의 값을 읽어서, 새로운 UInt16 형의 값을 생성하게 된다. (즉 변환이라기보다는 내부적으로는 삭제 + 생성 에 가깝다) 이러한 타입변환은 모든 타입이 가능한 것은 아니다. 새로운 타입( 개발자가 커스터마이징한 타입도 가능 ) 또한 type 을 extend 해서 새로운 타입을 건네 받을 수 있는 initializer 를 정의한다면 새로운 타입또한 SomeType(ofInitialValue) 을 통해 타입간의 변환이 가능합니다. 자세한 사항은 Extensions 문서에 서술되어 있습니다.

Integer and Floating-Point Conversion

정수와 실수 타입간의 변환은 명시되어야 합니다.
let three = 3 let pointOneFourOneFiveNine = 0.14159 let pi = Double(three) + pointOneFourOneFiveNine // pi equals 3.14159, and is inferred to be of type Double
Swift
복사
constant threeDouble 타입의 새 값을 생성하는데 사용되고 있습니다.
덧셈의 양쪽은 같은 타입이어야합니다. 이러한 타입 변환이 없다면 덧셈은 허용되지 않습니다.
부동소수점을 정수로 변환하는 것 또한 명시해주어야합니다. 정수 타입은 Double 또는 Float 값으로 초기화 가능합니다.
let integerPi = Int(pi) // integerPi equals 3, and is inferred to be of type Int
Swift
복사
실수 값들은 이러한 방식으로 새 정수형 값을 초기화 할 때 소수점을 떼어냅니다. 이것은 4.75 는 4 로, -3.9 는 -3 으로 초기화됩니다.
constant 와 variable 의 덧셈과 리터럴에 대한 덧셈의 규칙은 사뭇 다릅니다. 리터럴 값 3 은 0.14159 와 직접적으로 더해질 수 있습니다. 이는 리터럴이 그 자체로는 분명한 타입을 가지지 못하기 때문입니다. 리터럴들의 타입은 오직 컴파일러에 의해서 평가되고 추론됩니다.

Type Aliases

Type ALiases 는 이미 존재하는 타입에 새로운 별명을 정의해주는 것을 의미합니다. typealias 키워드를 활용해 별칭을 부여할 수 있습니다.
Type aliases 는 존재하는 type 을 맥락에 더 적합한 이름으로 바꾸어 사용하고자 할 때 사용합니다. 예를 들어 외부 소스의 구체적인 타입크기를 가지는 데이터를 다룰 때 사용됩니다.
typealias AudioSample = UInt16
Swift
복사
일단 한번 type alias 를 사용하게되면
이러한 별칭은 원래 타입의 이름을 사용하는 것과 똑같이 코드의 모든 부분에서 사용이 가능해집니다.
var maxAmplitudeFound = AudioSample.min // maxAmplitudeFound is now 0
Swift
복사
여기 AudioSample 은 Uint16 에 대한 별칭으로 지정되어 있습니다.
AudioSample.minUInt16.min 과 똑같이 동작합니다.

Boolean

Swift 에는 Bool 이라는 기초적인 Boolean 타입이 존재합니다. Boolean 값은 논리적으로 추론됩니다. 오직 true 또는 false 값만을 담을 수 잇습니다. Swift 는 두개의 Boolean constant 값 truefalse을 제공합니다.
let orangesAreOrange = true let turnipsAreDelicious = false
Swift
복사
orangesAreOrangeturnipsAreDelicious 의 타입은 Bool 형으로 추론됩니다. Boolean 리터럴 값과 함께 초기화가 되었기 때문에, . IntDouble 형처럼 Bool 타입을 명시할 필요없이 true 또는 false 로 그들을 설정하는한 constant 와 variable 의 선언이 가능합니다. 타입 추론은 Swift 코드를 더 간결하고 가독성있게 만듭니다.
Boolean 값은 특히 조건문을 사용할 때 유용합니다.
if turnipsAreDelicious { print("Mmm, tasty turnips!") } else { print("Eww, turnips are horrible.") } // Prints "Eww, turnips are horrible."
Swift
복사
if 문과 같은 조건문들은 Control Flow 문서에서 더 자세히 다루겠습니다.
Swift 의 타입 안정성은 Boolean 이 아닌 값이 Bool 값으로 대체되는 것을 막습니다.
아래의 코드는 컴파일에러가 발생합니다.
let i = 1 if i { // this example will not compile, and will report an error }
Swift
복사
위 코드의 대안은 아래와 같습니다.
let i = 1 if i == 1 { // this example will compile successfully }
Swift
복사
i == 1 비교의 결과는 Bool 타입이며, 이 두번째 예시는 type check 를 통과합니다.이와 같은 비교는 Basic Operators 문서에서 자세히 다루겠습니다.
Swift 의 type safety 덕분에 이러한 접근은 예기치 못한 에러를 피하게 해주고, 항상 특정 부분의 코드의 의도를 명확하게 해줍니다.

Tuples

튜플은 여러개의 값을 하나의 값으로 그룹화 합니다. 튜플 내부에 있는 값들은 어떠한 타입이든 가능하며, 서로 같은 타입일 필요가 없습니다.
예를들어 (404, "Not Found") 는 HTTP 의 Status code 를 나타내는 튜플입니다. HTTP status code 는 web page 요청시 마다 web server 가 반환하는 특별한 값입니다. 404 Not Found 라는 status code 는 웹페이지가 존재하지 않을 때 돌려받는 값입니다.
let http404Error = (404, "Not Found") // http404Error is of type (Int, String), and equals (404, "Not Found")
Swift
복사
(404, "Not Found") 튜플은 IntString 을 하나로 그룹화하여 HTTP status code 들을 두개의 분리된 값(숫자와 읽을 수 있는 설명)으로 제공합니다. 이 튜플은 (Int, String) 타입의 튜플 로 나타낼 수 있습니다
모든 타입으로 순회가능한 튜플을 작성할 수 있으며, 원하는 만큼 다양한 유형을 포함시킬 수 있습니다.
(Int, Int, Int), or (String, Bool) 이렇게 다른 타입을 가진 튜플도 순회가 가능합니다.
튜플의 구성요소를 각각의 다른 constant 와 variable 로 해체할 수 있습니다.
let (statusCode, statusMessage) = http404Error print("The status code is \(statusCode)") // Prints "The status code is 404" print("The status message is \(statusMessage)") // Prints "The status message is Not Found"
Swift
복사
튜플의 값중 일부만 필요하다면 underscore _ 를 활용해서 튜플을 해체하세요.
let (justTheStatusCode, _) = http404Error print("The status code is \(justTheStatusCode)") // Prints "The status code is 404"
Swift
복사
또는 각각의 원소를 index 를 활용해 접근할 수도 있습니다.
print("The status code is \(http404Error.0)") // Prints "The status code is 404" print("The status message is \(http404Error.1)") // Prints "The status message is Not Found"
Swift
복사
튜플을 정의할 때, 각각의 튜플의 원소에게 이름을 부여해줄 수 있습니다.
let http200Status = (statusCode: 200, description: "OK")
Swift
복사
만약 튜플 내부의 원소에게 이름을 부여해주었다면, 이러한 원소의 이름을 활용해 각각의 원소의 값에 접근할 수 있습니다.
print("The status code is \(http200Status.statusCode)") // Prints "The status code is 200" print("The status message is \(http200Status.description)") // Prints "The status message is OK"
Swift
복사
튜플들은 특히 함수의 리턴값으로 사용할 때 유용합니다. Webpage 를 불러오려는 함수는 (Int, String) 튜플 타입을 리턴하여서 페이지를 불러오는데 성공했는지, 또는 실패했는지를 알려줍니다. 하나의 값을 반환할 때보다 두개의 구분된 값, 다른 타입을 가지는 튜플을 반환함으로써 함수는 결과에 한 더 유용한 정보를 제공할 수 있습니다.
더 자세한 내용은 Functions with Multiple Return Values. 에서 확인하세요

Optionals

함수의 실패에 대한 핸들링
값이 존재하지 않는 상황에서 optional 을 사용할 수 있습니다. optional 은 두가지 상황을 나타낼 수 있습니다:
1.
값이 존재하며, optional 을 unwrap 해서 값에 접근할 수있습니다
2.
값이 존재하지 않습니다.
옵셔널의 개념은 C 나 Objective-C 에는 존재하지 않습니다. Objective-C 의 가장 가까운 것은 메서드의 객체 또는 nil(유효한 객체가 존재하지 않음) 을 리턴하는 능력입니다. 하지만 이러한 기능은 오직 객체에만 적용이 가능하며, structure, basic C type, enumeratoin 타입에는 사용이 불가능합니다. 이러한 타입들에 대해서, Objective C 의 메서드들은 보통 NSNotFound 와 같은 특별한 값을 리턴합니다. Swift 의 optional 은 모든 타입에 대해 값이 존재하지 않음을 나타낼 수 있습니다.
optional 이 어떻게 값이 존재하지 않는 상황을 대처하는 지를 보여주는 예시를 봅시다. Swift 의 Int 타입은 String 값을 Int 값으로 변경할 수 있는 initializer 를 가지고 잇습니다. 그러나 모든 문자열이 정수형으로 변경될 수 있는 것은 아닙니다. 문자열 '123' 은 numeric 값인 123 으로 변경될 수 있습니다. 하지만 "hello, world" 같은 문자열 들은 numeric 타입으로 변환할 수 없습니다.
아래의 예시는 Intinitializer 를 이용해 String 타입으로 변환한 예시입니다.
let possibleNumber = "123" let convertedNumber = Int(possibleNumber) // convertedNumber is inferred to be of type "Int?", or "optional Int"
Swift
복사
이러한 initializer 가 변환에 실패할 수 있기 때문에, optional 한 Int 값을 리턴합니다. optional 한 IntInt? 로 표기합니다. 물음표가 값이 optional 하다는 것을 나타내며, Int 형의 값을 가지고 있거나 어떠한 값도 가지지 않는 것을 의미합니다.
Int? 로 선언된 변수에는 String, Bool 값을 할당 못할 뿐더러, Int 값 또한 할당할 수 없습니다.

nil

nil 값을 이용해 optional 한 변수에 값이 존재하지 않음을 나타낼 수 있습니다.
var serverResponseCode: Int? = 404 // serverResponseCode contains an actual Int value of 404 serverResponseCode = nil // serverResponseCode now contains no value
Swift
복사
non-optional constant, variable 에 nil 값을 할당할 수 없습니다. constant 와 variable 에 값이 존재하지 않음을 다루어야한다면 반드시 optional 한 데이터 타입으로 선언하십시오
만약 optional 변수를 초기값없이 정의한다면, 변수는 자동으로 nil 값으로 설정됩니다.
var surveyAnswer: String? // surveyAnswer is automatically set to nil
Swift
복사
Swift 의 nil 은 Ojective C 의 nil 과는 다릅니다. Objective C 에서의 nil 은 존재하지 않는 객체에 대한 포인터입니다. 반면 Swift 에서 nil 은 포인터가 아닙니다. Swift 에서의 nil 은 특정 타입의 값의 부재를 나타내며, optional 로 선언 된 모든 타입은 nil 이 할당가능합니다.

If Statements and Forced Unwrapping

if문을 활용하여 optional 이 담고있는 값이 nil 값인지를 비교할 수 있습니다.
만약 optional 이 값을 가지고있다면 nil 값과 다르다 라고 판단합니다.
if convertedNumber != nil { print("convertedNumber contains some integer value.") } // Prints "convertedNumber contains some integer value."
Swift
복사
optional 의 값이 존재함을 명확히 했다면, 이제 optional 의 값을 느낌표를 활용하여 접근할 수 있게됩니다. 느낌표는 " 값이 존재함을 분명하게 알고 이값을 사용하겠다" 라는 의미로 사용됩니다. 이것이 바로 optional 값의 Forced unwrapping 입ㄴ디ㅏ.
if convertedNumber != nil { print("convertedNumber has an integer value of \(convertedNumber!).") } // Prints "convertedNumber has an integer value of 123.
Swift
복사
더 자세한 내용은 Control Flow 에서 알아볼 수 있습니다.
느낌표를 사용하여 값이 존재하지 않는 optional 에 접근하려 한다면 runtime error 가 발생합니다. 항상 optional 에 값이 존재함을 확신할 때에만 느낌표를 활용하여 force-unwrap 하세요

Optional Binding

옵셔널 바인딩을 활용하여 값이 존재 여부를 확인하고, 존재한다면 이에 대한 임시 constant 또는 variable 을 사용할 수 있습니다. 옵셔널 바인딩은 if 문 과 while 문에서 optional 안의 값을 체크하기위해 사용 됩니다. 옵셔널 바인딩을 이용해서 값을 추출해 constant 또는 variable 에 저장해 단순한 동작을 구현할 수 있습니다.
if 문을 활용한 옵셔널 바인딩 은 아래와 같이 사용합니다.
if let constantName = someOptional { statements }
Swift
복사
Optionals 파트에서 본 possibleNumber 에 대한 코드 예시를 옵셔널 바인딩을 활용해 다시 적어볼 수 있습니다.
if let actualNumber = Int(possibleNumber) { print("The string \"\(possibleNumber)\" has an integer value of \(actualNumber)") } else { print("The string \"\(possibleNumber)\" couldn't be converted to an integer") } // Prints "The string "123" has an integer value of 123"
Swift
복사
이 코드의 의미는 아래와 같습니다.
Int(possibleNumber) 에 의해 반환된 옵셔널 Int 가 값을 가지고 있다면 이 값을 새로운 constant 인 actualNumber 에 할당한다.
만약 변환이 성공적이라면 actualNumber constant 는 첫번째 branch 내에서 사용이 가능해집니다. 이 branch 내에서는 이미 optional 의 값으로만 할당된 새로운 constant 가 존재하므로 값에 접근하기 위해 느낌표를 사용하지 않아도 됩니다.
let 대신 var 을 사용하여 이러한 옵셔널 값을 varaible 로 사용도 가능하다.
하나의 if 문에 옵셔널 바인딩을 포함해 여타 다른 Boolean condition 을 추가할 수 있다.
옵셔널 바인딩의 값중 하나라도 nil 이거나 Boolean condition 이 false 라면 전체 if 문이 거짓인 것으로 고려된다.
if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 { print("\(firstNumber) < \(secondNumber) < 100") } // Prints "4 < 42 < 100" if let firstNumber = Int("4") { if let secondNumber = Int("42") { if firstNumber < secondNumber && secondNumber < 100 { print("\(firstNumber) < \(secondNumber) < 100") } } } // Prints "4 < 42 < 100"
Swift
복사
옵셔널 바인딩으로 생성된 상수와 변수는 오직 if 문안에서만 사용이가능하다. 하지만 guard 문을 통해 생성된 변수와 상수는 guard 문 이후의 코드라인에서도 사용가능하다
옵셔널 바인딩 이후의 action에 대한 코드가 길어진다면 guard 문을 사용하자

Implicitly Unwrapped Optionals

옵셔널 이기는 하지만, 값이 무조건 존재, 이 값을 일반 변수처럼도 사용가능한 타입.
프로그램의 구조상 값이 항상 존재할 수 밖에 없는 경우에는 값의 존재여부가 명확하므로 이러한 종류의 옵셔널 들은 unwrap 이 필요 없다.
이러한 옵셔널들을 Implicitly unwrapped optional 이라고한다.
옵셔널의 선언 시 타입 뒤에 느낌표를 사용해 Implicitly unwrapped optional 를 만들 수 있다.
let possibleString: String? = "An optional string." let forcedString: String = possibleString! // requires an exclamation point let assumedString: String! = "An implicitly unwrapped optional string." let implicitString: String = assumedString // no need for an exclamation point
Swift
복사
1.
초기값과 함께정의한다.
2.
타입 뒤에 느낌표를 붙인다.
보통 class 의 초기화 과정에 사용된다.
향후 이 optional 에는 값에 대한 직접적인 접근이 가능하다. 그러나 주의 사항이 있다.
1.
컴파일러는 이를 optional 타입으로 인식한다.
a.
옵셔널 바인딩을 이용해 타입전환이 가능하다.
if let definiteString = assumedString { print(definiteString) } // Prints "An implicitly unwrapped optional string."
Swift
복사
2.
nil 값이 할당될 수 있는 경우 이를 사용하지 말아야 한다.
3.
Implicitly unwrapped optional 을 nil 값과 비교할 수 없다.
옵셔널 타입이 아닌 변수에 느낌표를 사용하는 것과 같다.
if assumedString != nil { print(assumedString!) } // Prints "An implicitly unwrapped optional string."
Swift
복사
let optionalString = assumedString // The type of optionalString is "String?" and assumedString isn't force-unwrapped.
Swift
복사

Error Handling

에러 핸들링을 사용해서 실행중에 마주할 수 있는 에러 상황에 대처할 수 있다.
실패의 원인을 확인할 수 있으며 필요하다면 프로그램의 다른 부분으로 에러를 전송할 수 있다.
함수가 error condition 을 마주한다면 error 를 throw 한다. 이렇게 하면 함수를 호출한 부분에서 이러한 error 를 catch 할 수 있고 적절하게 대처가 가능하다.
func canThrowAnError() throws { // this function may or may not throw an error }
Swift
복사
위 함수는 throws 키워드와 함께 선언함으로써 에러를 throw 할 수 있음을 나태난다.
에러가 발생될 수 있는 함수를 호출할 때는 항상 try 키워드를 이용해 함수를 호출해야한다.
Swift는 자동으로 현재 scope 의 에러를 전송한다. catch 에 의해서 핸들링이 될 때까지.
// 에러에 대한 케이스를 enum 타입으로 정리해야함 enum VendingMachineError: Error { case invalidSelection case insufficientFunds(coinsNeeded: Int) case outOfStock } struct Item { var price: Int var count: Int } class VendingMachine { var inventory = [ "Candy Bar": Item(price: 12, count: 7), "Chips": Item(price: 10, count: 4), "Pretzels": Item(price: 7, count: 11) ] var coinsDeposited = 0 // 가드 문과 함께 throw 키워드 사용. func vend(itemNamed name: String) throws { guard let item = inventory[name] else { throw VendingMachineError.invalidSelection } guard item.count > 0 else { throw VendingMachineError.outOfStock } guard item.price <= coinsDeposited else { throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited) } coinsDeposited -= item.price var newItem = item newItem.count -= 1 inventory[name] = newItem print("Dispensing \(name)") } } var vendingMachine = VendingMachine() vendingMachine.coinsDeposited = 8 //이렇게 던져진 에러 case 는 do catch 문으로 처리가능. do { try vendingMachine.vend(itemNamed: "Pretzels") } catch VendingMachineError.invalidSelection { // } catch VendingMachineError.insufficientFunds(_) { // } catch VendingMachineError.outOfStock { // }
Swift
복사
makeASandwich() 함수가 에러를 발생 시킬 수 있다. 이 함수는 do {} 안에서 호출되었기 때문에, 발생한 에러는 catch 로 전달된다. 이렇게 전달된 에러의 case 가 SandwichError.outOfCleanDishes 와 일치한다면, washDishes() 가 호출된다. 만약 에러가 SandwichError.missingIngredients 가 일치한다면 buyGroceries(_:) 가 호출된다. catch 패턴에 의해 buyGroceries(_:) 이 함수는 연관된 [String] 타입의 값과 함께 호출된다.
자세한내용은 에러핸들링문서에서 다루겠다.

Assertions and Precondtions (예외처리)

assert() : 코드가 실행될 때 반드시 만족해야하는 조건을 코드에 명시해 놓은 것.
리턴값 false : 프로그램 무효화,앱 종료
1.
디버깅 모드에서만 작동한다 ( 아무리 많이 사용해도 괜찮다)
2.
실제 앱성능에는 영향을 끼치지 않는다.
3.
프로그래머의 실수를 추적하는데 사용된다.
precondition() : 조건을 만족하지 못하면 다음 플로우가 진행되지 않는다.
리턴값 false : 프로그램 무효화,앱 종료
1.
외부 요인에 의한 에러를 추적하는 데 사용된다.
2.
디버깅 모드에서도 작동하며, 빌드 시에도 작동한다.

Assertion 을 이용한 디버깅

let age = -3 assert(age >= 0, "A person's age can't be less than zero.") // This assertion fails because -3 isn't >= 0.
Swift
복사
위 예시에서 age >= 0 가 참이면 코드는 계속 실행된다. 하지만 false 이면 assertion 이 fail 하고 앱을 종료한다.
만약 코드가 이미 실행에 필요한 condition 을 점검했다면 assertionFailure(_:file:line:) 을 사용해서 assertion 이 fail 되었음을 나타낼 수 있다.
if age > 10 { print("You can ride the roller-coaster or the ferris wheel.") } else if age >= 0 { print("You can ride the ferris wheel.") } else { assertionFailure("A person's age can't be less than zero.") }
Swift
복사

Enforcing Preconditions

condtion 이 false 일 가능성이 존재할 때마다 precondition 사용한다. 실행을 위해서는 반드시 true 여야한다.
precondition(_:_:file:line:) 함수를 호출함으로써 사용이 가능하다. 이 함수에는 condition 을 평가하는 표현과 이 평가가 false 일 경우에 출력할 결과 메시지를 건네줄 수 있다.
// In the implementation of a subscript... precondition(index > 0, "Index must be greater than zero.")
Swift
복사
preconditionFailure(_:file:line:) 함수를 이용해서 실패가발생했음을 나타낼수 있다.
예를들면,
sitch 문의 default case 에 사용이 가능하다. 모든 유효한 데이터가 다른 case 문에서 다루어졌을 때 사용해야한다.
unchecked mode (Ounchecked) 에서 컴파일 하면 precondtion 을 무시한다.
컴파일러는 precondition 을 모두 true 라고 가정하고, 코드를 그에 따라 최적화한다.
하지만 위 모드에서도 fatalError("Unimplemented") 함수는 이러한 모드 설정과는 무관하게 실행을 멈춰 세운다.
fatalError(_:file:line:) 함수를 이용해기능적으로 아직 구현되지 않은 것들을 개발하려고할 때 프로토 타이핑에 이용할 수 있다. fatalError(_:file:line:) 함수는 어떠한 모드에서건 넘어가지 않고 앱을 멈춰세운다. ( assertion 과 precondition 은 그렇지 않다.)