티스토리 뷰

반응형

안녕하세요 Pingu입니다!

Swift를 처음 공부하는데, 공식 문서를 통해 자세하게 Swift언어에 대해 알아보려고 합니다.

 

이번 글은 Swift 공식 문서의 첫 번째 단원인 The Basics를 읽고 정리를 해보려고 합니다.

 

Apple 공식 문서 1단원 The Basics

The Basics

Swift는 IOS, macOS, watchOS, tvOS를 만들기 위한 새로운 프로그래밍 언어입니다. 기초적인 자료형으로는 Int, Double, Float, Bool, String, Array, Set, Dictionary가 있습니다. C언어와 마찬가지로 Swift는 값을 저장하고 참조하기 위해 변수를 사용하고 이름으로 변수를 구분합니다. Swift에는 변수 중에서도 값을 변경할 수 없는 Constant(상수)를 제공하고 이로 인해 C에서 보다 더 많은 기능을 수행할 수 있습니다. Swift에는 Objective-C에서는 볼 수 없는 tuple(튜플) 형식도 제공합니다. 튜플을 사용해서 여러 값을 하나의 값으로 반환할 수도 있습니다. Swift에서는 Optional Type(옵셔널 타입)을 제공하는데, 이는 값이 없을 때를 제어할 수 있습니다. 만약 값이 있다면 값을, 값이 없다면 nil을 사용합니다. 이는 클래스뿐만 아니고 모든 유형에 대해 사용할 수 있습니다. Swift는 type-safe 언어입니다. 즉 사용자가 잘못된 자료형을 사용하면 경고를 줘서 인지하게 해 줍니다. 이는 옵셔널 타입에도 적용됩니다. 예를 들어 일반 String 변수에 옵셔널 String 변수를 사용하려고 하면 오류를 발생시킵니다.


Constants and Variables (상수와 변수)

상수는 한 번 정의되면 값이 절대로 변하지 않는 값을 말하며 변수는 값이 변할 수 있는 값입니다. 상수는 let으로 선언되며 변수는 var로 선언할 수 있습니다.

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

let maximumNumberOfLoginAttempts = 10
var currentLoginAttemp = 0

위의 코드처럼 상수, 변수를 선언할 수 있습니다.

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

위의 코드처럼 여러 상수나 변수를 한 줄에 선언할 수도 있습니다.

Type Annotations

변수나 상수를 선언할 때 type annotation을 사용할 수 있습니다. 이는 어떠한 자료형으로 변수나 상수를 선언할지 명확하게 하기 위해 사용됩니다.

var welcomeMessage: String

위의 코드처럼 type annotation을 사용할 수 있습니다. 이제 위에서 선언한 welcomeMessage에는 어떠한 String 자료형도 오류 없이 새로 초기화 될 수 있습니다.

welcomeMessage = "Hello"

물론 아까와 같이 여러 변수나 상수를 type annotation을 사용하여 한 줄에 선언할 수 있습니다.

var red, greem, blue: Double

Naming Constants and Variables (상수와 변수에 이름 짓기)

변수와 상수는 유니코드에 있는 모든 문자열로 이름을 지을 수 있습니다.

let π = 3.14159
let 你好 = "你好世界"
let 🐶🐮 = "dogcow"

변수와 상수의 이름에는 띄어쓰기(공백)이 존재할 수 없고 수학 기호, 화살표, private-use Unicode scalar values, line- and box- drawing 문자를 사용할 수 없습니다. 또한 숫자로 시작할 수는 없지만 시작 말고 다른 곳에는 포함될 수 있습니다. 한번 상수 혹은 변수로 선언되면 같은 이름으로 다른 상수나 변수를 만들 수 없고 자료형을 바꿀 수도 없습니다. 상수로 선언된 것을 변수로 바꾸거나 변수로 선언된 것을 상수로 바꿀 수도 없죠. 물론 상수에는 한 번 선언된 값이 변경될 수도 없습니다.

Printing Constants and Variables (상수와 변수 출력)

상수나 변수는 print(_:separator:terminator:) 함수로 출력할 수 있습니다.

var friendlyWelcome = "Hello"
print(friendlyWelcome)

print 함수는 하나 이상의 값을 콘솔 창에 출력해 주는 함수입니다. separator, terminator에는 default값이 있어 함수를 호출할 때 꼭 매개변수에 무엇인가를 주지 않아도 됩니다. terminator는 종결자라는 의미로 기본적으로 줄 바꿈이 있어 print 함수를 호출하면 줄 바꿈이 되는데, 이를 줄 바꿈 없이 다른 것으로 바꾸고 싶다면 다른 값을 넣어주면 됩니다. (예: print(someValue, terminator: "")) Swift는 문자열 보간을 사용해서 문자열에 상수나 변수의 현재 값을 출력할 수 있습니다.

print("The current value of friendlyWelcome is \(friendlyWelcome)")

위의 코드처럼 백슬래시와 괄호로 문자열 보간을 사용할 수 있습니다.


Comments (주석)

주석을 사용해서 실행되지 않는 텍스트를 추가해서 메모를 하거나 설명을 할 수 있습니다.

// This is a comment.

주석은 위의 코드와 같이 //를 사용하면 해당 줄만 주석 처리됩니다.

/* This is also a comment
but is written over multiple lines. */

/*, */로 묶여있는 주석은 여러 줄을 한 번에 주석 처리할 수 있게 해 줍니다. C언어와는 다르게 주석 안에 다른 주석이 중첩될 수 있습니다.

/* This is the start of the first multiline comment.
 /* This is the second, nested multiline comment. */
This is the end of the first multiline comment. */

Semicolons (;)

다른 몇 개의 언어와 마찬가지로 Swift에서도 코드 마지막에 세미콜론(;)을 쓰지 않아도 됩니다. 근데 정 쓰고 싶다면 써도 된다고 합니다. 하지만 한 줄에 여러 개의 실행문을 쓰고 싶다면 세미콜론을 꼭 써줘야 합니다.

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

Integers (정수)

Integers는 42, -23과 같이 분수 성분이 없는 수입니다. 양수, 0, 음수가 정수에 포함됩니다. Swift는 8, 16, 32, 64비트 형식의 부호 있는 정수와 부호 없는 정수를 제공합니다. C언어와 비슷하게 부호 없는 정수는 UInt8과 같이 나타내며 부호 있는 정수는 Int8 같이 나타냅니다. Swift의 모든 타입과 마찬가지로 정수 타입도 대문자로 시작됩니다.

Integer Bounds (정수의 한계값)

min, max 프로퍼티를 사용하여 각 정수 타입의 최댓값과 최솟값에 접근할 수 있습니다.

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

Int

대부분의 경우에서 정수형을 사용할 때 크기를 선택할 필요는 없고 Int만 사용하면 됩니다. Int를 사용할 때 컴퓨터가 32비트 플랫폼이라면 Int32로 64비트 플랫폼이라면 Int64로 알아서 정의됩니다. Int32도 -2,147,483,648 ~ 2,147,483,647 사이의 값을 저장할 수 있으므로 충분히 크다고 볼 수 있습니다.

UInt

Swift는 부호가 없는 정수도 제공합니다. 물론 UInt도 Int와 마찬가지로 플랫폼에 따라 알아서 정의됩니다.


Floating-Point Numbers (부동소수점)

부동 소수점 숫자는 3.14159 , 0.1, -273,15 와 같이 분수형 숫자입니다. 부동 소수점 숫자는 정수형 보다 넓은 범위의 값을 나타낼 수 있고,  Swift에서는 Double, Float의 두 가지 부동 소수점 타입을 제공합니다. Double은 64 비트 부동 소수점, Float는 32 비트 부동 소수점입니다. Double의 정밀도는 십진수 15 자리 이상이고 Float의 정밀도는 십진수 6자리입니다. 적절한 부동 소수점 타입은 코드에서 작업해야 하는 값의 특성과 범위에 따라 달라진다고 합니다.


Type Safety and Type Inference 

Swift는 Type-safe 언어입니다.. 즉 잘못된 자료형을 사용하면 컴파일러가 화를 내(?)줍니다. 따라서 개발자는 오류를 빨리 발견할 수 있습니다. Type-Checking은 다른 타입을 사용하려고 할 때 오류를 발생시켜서 오류를 피할 수 있습니다. 하지만 미리 자료형을 선언하지 않으면 Swift는 type-inference를 통해 적절한 타입을 찾습니다. type-inference를 통해 컴파일러는 코드를 컴파일할 때 자동으로 자료형을 추론할 수 있습니다. Type-inference 때문에 swift는 C와 Objective-C와는 다르게 자료형 선언이 필수적이지 않습니다. 하지만 상수, 변수 선언을 위한 let, var는 꼭 써줘야 합니다.

let meaningOfLife = 43
// meaningOfLife is inferred to be of type Int

이렇게 자료형을 정의해 주지 않아도 Swift는 알아서 Int 형일 것이라고 추론합니다.

let pi = 3.14159
// pi is inferred to be of type Double

Swift는 부동 소수점을 추론할 때는 항상 Double로 추론합니다.

let anotherPi = 3 + 0.14159
// anotherPi is also inferred to be of type Double

3에는 명시적인 유형이 없고 뒤에 나오는 0.14159에 부동 소수점 숫자가 존재하므로 Double로 추론합니다.


Numeric Literals

정수형 리터럴은 아래와 같이 나타낼 수 있습니다. 10진수는 접두사가 없고, 2진수는 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

부동 소수점 숫자에서는 10진수는 접두사가 없고, 16진수일 때 0x 접두사가 붙습니다. 부동 소수점에는 e로 표시되는 지수를 가질 수도 있습니다.

1.25e2  = 1.25 x 102, or 125.0.

1.25e-2 = 1.25 x 10-2, or 0.0125.

16진수에서는 e가 아닌 p로 지수를 표현합니다.

0xFp2 means 15 x 22, or 60.0.

0xFp-2 means 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를 써야 합니다. 이렇게 해야 어떠한 경우에도 정수형 상수와 변수가 상호적으로 사용될 수 있기 때문입니다. 크기가 지정된 데이터, 성능, 메모리 등의 최적화 등 특별한 경우에만 Int가 아닌 다른 정수형 타입을 사용하는 게 좋습니다. 이렇게 사용하면 미리 사용했다고 문서화를 해두는 것을 추천합니다!

Integer Conversion

정수 상수 또는 변수에 저장될 수 있는 숫자의 범위는 정수 타입마다 다릅니다. 예를 들어 Int8 은 -128에서 127까지의 숫자만 저장 가능하고 UInt8은 0에서 255의 숫자를 저장할 수 있습니다. 만약 이를 초과한 값을 넣게 되면 오류를 발생합니다.

let cannotBeNegative: UInt8 = -1
// UInt8 cannot store negative numbers, and so this will report an error
let tooBig: Int8 = Int8.max + 1
// Int8 cannot store a number larger than its maximum value,
// and so this will also report an error

이는 각자의 정수 타입마다 저장할 수 있는 값이 다르기 때문입니다. 즉 사용을 위해 다른 정수 타입으로 변환을 해주어야 합니다.

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

위의 코드와 같이 다른 타입의 정수형을 직접 더할 수 없기 때문에 UInt16()을 사용하여 UInt8을 UInt16으로 변환한 뒤 더해주었습니다. 물론 twoThousandAndOne의 타입도 UInt16이 됩니다.

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

three는 정수형이고 pointOneFourOneFiveNine은 부동소수점 숫자이므로 같은 타입으로 변환한 뒤 더해줄 수 있습니다.

let integerPi = Int(pi)
// integerPi equals 3, and is inferred to be of type Int

만약 위와 같이 부동소수점 숫자를 정수형으로 바꿔주면 소수점 아래 숫자를 모두 버리게 됩니다. 즉 3.14159에서 3만 남게 됩니다.


Type Aliases

타입의 별명이라고 볼 수 있는 Type Aliases는 기존 타입을 다른 이름으로 선언하는 것 입니다.

typealias AudioSample = UInt16

이렇게 하면 UInt16 타입을 AudioSample이라는 이름으로도 접근할 수 있게 됩니다.


Booleans

Swift에는 기본적인 Boolean type으로 Bool을 가지고 있습니다.

이는 오로지 true, false만을 값으로 가질 수 있습니다.

let orangesAreOrange = true
let turnipsAreDelicious = false

위의 코드처럼 상수나 변수를 생성하자마자 true, false로 설정하면 Bool로 선언할 필요가 없습니다. Boolean 값은 if와 같은 조건문에서 유용하게 사용될 수 있습니다.

if turnipsAreDelicious {
    print("Mmm, tasty turnips!")
} else {
    print("Eww, turnips are horrible.")
}
// Prints "Eww, turnips are horrible."

Swift는 Type-safe 언어이기 때문에 Bool 자료형이 와야 하는 곳에 다른 자료형이 오게 되면 당연히 오류를 발생시킵니다. 아래와 같이 기본 연산자로도 Bool 자료형을 선언할 수 있습니다.

let i = 1
if i == 1 {
    // this example will compile successfully
}

Tuples

Tuple(튜플)은 여러 개의 값을 하나의 복합 값으로 그룹화하는 것을 말합니다. 튜플 내의 값은 모든 자료형이 가능합니다. 하나의 자료형만 가능한 것이 아니고 여러 개의 자료형이 함께 존재해도 상관없습니다.

let http404Error = (404, "Not Found")
// http404Error is of type (Int, String), and equals (404, "Not Found")

위의 코드와 같이 404라는 정수형과 "Not Found"라는 문자열이 함께 사용되어도 상관이 없습니다. 개발자는 필요한 자료형을 넣은 튜플을 만들 수 있습니다.

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"

개발자가 튜플의 값들 중 몇 개의 값만 필요하다면 _를 사용하면 됩니다.

let (justTheStatusCode, _) = http404Error
print("The status code is \(justTheStatusCode)")
// Prints "The status code is 404"

튜플의 값에 접근하는 방법으로는 인덱스를 사용하는 방법도 있습니다.

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"

새로운 튜플을 만들 때 각자의 값에 이름을 붙여주고 싶으면 아래와 같이 선언하면 됩니다.

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

위와 같이 선언한 튜플의 값에는 이름으로도 접근이 가능합니다.

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"

튜플은 함수의 반환 값으로 사용하면 유용합니다. 예를 들어 웹페이지 검색의 성공 또는 실패를 설명하기 위해 (Int, String) 튜플 타입을 사용할 수 있습니다.


Optionals

개발자는 Optional(옵셔널)을 비어있는 값을 표현할 때 사용할 수 있습니다. 옵셔널은 두 가지 상태를 표현합니다. 값이 있거나, 없거나가 그 두 가지입니다. 따라서 개발자는 옵셔널을 사용할 땐 옵셔널을 뜯어봐서 값이 있는지 없는지 확인해야 합니다. 예를 한 번 보겠습니다.

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// convertedNumber is inferred to be of type "Int?", or "optional Int"

String 타입의 값을 Int 타입으로 바꿔 줄 수 있는데, 항상 바뀌는 것은 아닙니다. "123"과 같은 String 타입은 Int 타입으로 바꿔줄 수 있지만 "Hello"와 같은 String 타입은 바꿀 수 없습니다. 즉 실패할 수 있는 경우에 Int 대신 Int?를 사용하면 성공하면 Int를 넣고 실패하면 nil을 넣음으로써 오류를 방지할 수 있습니다. 자료형 뒤에?를 붙이면 옵셔널 타입으로 선언하는 것입니다. 하지만 Int?로 선언하면 Int형과 nil만 들어갈 수 있지 String이나 Bool과 같은 다른 타입들은 들어갈 순 없습니다.

nil

var serverResponseCode: Int? = 404
// serverResponseCode contains an actual Int value of 404
serverResponseCode = nil
// serverResponseCode now contains no value

위와 같이 정수형 옵셔널로 선언된 값에 nil을 넣어주면 더 이상 serverResponseCode에는 값이 존재하지 않게 됩니다.

var surveyAnswer: String?
// surveyAnswer is automatically set to nil

만약 옵셔널 변수를 선언한 뒤 아무것도 넣지 않으면 Swift에서 자동적으로 nil을 넣습니다.

If Statements and Forced Unwrapping

개발자는 옵셔널에 값이 있는지 없는지를 확인하기 위해 뜯어봐야 하는데 이때 if를 사용할 수 있습니다.

if convertedNumber != nil {
    print("convertedNumber has an integer value of \(convertedNumber!).")
}
// Prints "convertedNumber has an integer value of 123."

이렇게 convertedNumber이라는 변수가 nil이 아니면 조건 문의 코드를 실행하게 됩니다. 또한 해당 변수 뒤에!를 붙이게 되면 nil이 아닌 그 변수에 존재하는 값을 추출하여 사용하게 됩니다. 만약 값이 없는데 !를 붙여 꺼내려고 하면 오류가 발생하므로 위와 같이 옵셔널이 nil 인지 아닌지를 확인 후 사용해야 합니다.

 

Optional Binding

Optional Binding(옵셔널 바인딩)은 옵셔널에 값이 있는지 본 뒤 있다면 해당 값을 가지는 상수나 변수를 만들고 사용할 수 있게 하는 것입니다. 옵셔널 바인딩에는 if, while 문이 사용될 수 있고 사용법은 아래와 같습니다.

if let actualNumber = Int(possibleNumber) {
    print("The string \"\(possibleNumber)\" has an integer value of \(actualNumber)")
} else {
    print("The string \"\(possibleNumber)\" could not be converted to an integer")
}
// Prints "The string "123" has an integer value of 123"

possibleNumber는 옵셔널 변수입니다. if let을 사용하여 만약 possibleNumber에 값이 있다면 actualNumber라는 상수에 값을 넣어 조건문에서만 사용할 수 있게 합니다. 만약 nil이라면 actualNumber는 만들어지지 않습니다. 이때 앞의 글에서 본 것처럼 !를 사용하지 않아도 actualNumber에는 possibleNumber의 값이 존재하게 됩니다. 물론 let 말고 var를 사용하여 변수처럼 사용할 수도 있습니다.

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"

여러 개의 옵셔널 바인딩을 한 번에 사용할 수도 있습니다.

Implicitly Unwrapped Optionals

앞에 글에서처럼 옵셔널을 사용하려면 if를 사용하여 값이 존재하는지 확인한 뒤 옵셔널 바인딩으로 값에 접근할 수 있었습니다. 만약 절대로 nil이 아닌 값이 존재하는 값이 존재한다면 어떨까요? 이럴 때는 if let과 같은 구문을 사용하지 않고 바로 접근하면 편할 것 같습니다. 이럴 때 바로 값에 접근할 수 있는 방법이 !를 붙이는 것입니다. 옵셔널 변수 선언 시?를 붙이면 암시적 옵셔널, !를 붙이면 명시적 옵셔널이 됩니다.! 를 붙인 옵셔널은 처음 정의된 후에는 값이 존재한다고 보고 앞으로 모든 시점에서 존재한다고 확신할 수 있을 때 유용합니다. Swift에서는 주로 클래스 초기화할 때 사용됩니다.

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

forcedString에서 possibleString에 !를 붙여주는 이유는 possibleString이 ?를 붙여준 암시적 옵셔널 변수이기 때문입니다. 하지만 처음 선언부터 !를 붙여 정의한 assumedString 같은 경우에는 다른 변수에서 사용할 때 !를 붙여주지 않아도 되는 것을 볼 수 있습니다.

let optionalString = assumedString
// The type of optionalString is "String?" and assumedString isn't force-unwrapped.

만약 암시적으로 선언된 옵셔널이 nil인데 명시적 옵셔널이 접근하려고 하면 런타임 오류가 발생합니다.

if assumedString != nil {
    print(assumedString!)
}
// Prints "An implicitly unwrapped optional string."

즉 그러한 런타임 오류를 방지하기 위해 위와 같이 사용하면 됩니다.


Error Handling

프로그램에서 오류가 발생하면 오류 처리를 사용하여 해결해야 합니다. 오류 처리를 통해 실패 원인을 알아내고 발생한 오류를 다른 부분으로도 전파할 수 있습니다. 만약 함수에서 에러가 발생되면 throws를 사용하여 에러를 던질(?) 수 있습니다. 그런 뒤 catch를 사용해 던져진 에러를 잡아 반응할 수 있습니다.

func canThrowAnError() throws {
    // this function may or may not throw an error
}
do {
    try canThrowAnError()
    // no error was thrown
} catch {
    // an error was thrown
}

만약 canThrowAnError에서 에러가 발생하면 오류를 던져 catch 구문을 실행합니다. 에러가 발생하지 않으면 그냥 함수를 수행한다. 여기서 do try 구문은 한 번 실행해볼까? 하고 실행을 했는데 실행한 함수가 throws로 오류를 던지면 catch를 받아 처리한다는 느낌으로 이해하면 쉽습니다.

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

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

조금 더 구체적인 예를 보면 위와 같습니다. makeASandwich 함수를 실행하려고 했는데 만약 오류가 발생하면 catch 구문을 아니면 그냥 makeASandwich 실행 후 eatASandwich 함수를 실행한다는 의미입니다. 여기서 SandwichError.outOfCleanDishes나 SandwichError.missingIngredients(let ingredients)는 위에서는 생략되었지만 개발자가 미리 선언한 에러의 종류입니다. 즉 에러의 종류에 따라 실행할 코드를 달리하는 것이라고 볼 수 있습니다. 이는 나중에 Error Handling 단원에서 자세히 알아보겠습니다.


Assertions and Preconditions

Assertions and Preconditions은 런타임 시 발생하는 것들을 확인하는 것입니다. 추가 코드를 실행하기 전에 사용해서 조건들이 맞는지 확인할 수 있습니다. 만약 조건들이 false로 나오게 되면 코드 실행이 중단되고 프로그램이 종료됩니다. Assertion은 개발과정에서 실수를 잡고 preconditions는 문제를 감지하는 데 도움을 줍니다. 

 

앞에서 본 Error Handling 과는 다르게 Assertions and Preconditions는 복구 가능하거나 예상되는 오류에는 사용되지 않습니다. 이는 발견 즉시 프로그램을 종료하기 때문입니다. 하지만 바로 종료하기 때문에 잘못된 상태로 인한 피해를 줄일 수 있습니다. 또한 종료가 되어버리기 때문에 오류를 쉽게 디버깅할 수 있습니다. 

 

Assertions과 Precondition의 조건들을 확인할 때 차이가 납니다.. Asserions는 디버그 빌드에서만 체크를 하지만 Preconditions는 디버그, 프로덕션 빌드 모두 체크합니다. 프로덕션 빌드에서는 Assertion이 체크되지 않기 때문에 프로덕션 성능에 영향을 주지 않으면서 Assertion을 사용할 수 있습니다.

Debugging with Assertions

Assertion은 assert(::file:line:) 함수로 사용할 수 있습니다.

let age = -3
assert(age >= 0, "A person's age can't be less than zero.")
// This assertion fails because -3 is not >= 0.

assert 함수의 조건을 확인하고 true 면 그냥 진행하고 false 면 프로그램을 종료하며 만약 오류 구문을 적어뒀다면 그것이 출력됩니다.

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.")
}

만약 조건이 이미 체크됐다면 assertionFailure(_:file:line:) 함수를 사용해 실패를 알릴 수 있습니다.


Enforcing Preconditions

precondition은 조건이 거짓이 될 가능성이 있지만 코드가 실행되기 위해선 반드시 참이어야 할 때 사용합니다. precondition(::file:line:) 함수로 사용할 수 있고 만약 조건이 false라면 설정해둔 오류 구문을 출력합니다.

// In the implementation of a subscript...
precondition(index > 0, "Index must be greater than zero.")

preconditionFailure(_:file:line:) 함수를 사용해서 실패가 발생했다는 것을 표시할 수 있습니다. 만약 uncheckedmode(-Ounchecked) 라면 preconditions는 체크되지 않습니다. 이때 컴파일러는 조건들이 모두 참이라고 생각하고 진행합니다. 그러나 fatalError(_:file:line:) 함수는 이와 관계없이 항상 체크되고 프로그램을 중지시킵니다. 개발자는 fatalError(_:file:line:) 함수를 개발 초기에 사용하여 치명적인 오류에 대해 항상 중지되도록 설정할 수 있습니다.

 

감사합니다.

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함