상수와 변수(Constants and Variables)
상수와 변수는 이름과 특정 타입의 값을 연결합니다. 상수(Constant)의 값은 최초 지정 후 변경이 불가능하지만 변수(Variable)는 다른 값으로 변경이 가능합니다. 상수는 let 키워드로 선언하고, 변수는 var 키워드로 선언합니다.
// 상수
let str = "Constants"
// 변수
var str = "Hello Swift"
str = "Variable"
타입 명시(Type Annotations)
상수 또는 변수를 선언할 때 타입을 명확하게 하기 위해 타입 명시를 할 수 있습니다. 타입을 명시하는 방법은 상수 또는 변수의 이름 뒤에 콜론과 공백 한칸 뒤에 사용할 타입을 적으면 됩니다.
var str: String = "Hello Swift"
또한, 아래와 같이 마지막 변수 뒤에 타입을 명시하면 같은 타입의 여러개의 변수를 한번에 선언할 수 있습니다.
var red, green, blue: Double
상수와 변수의 이름(Naming Constants and Variables)
상수와 변수 이름은 Unicode) 문자를 포함하여 대부분의 문자를 포함할 수 있습니다. 다만, 숫자로 시작하는 일므은 선언할 수 없습니다.
let n = 3.14159
let 你好 = "你好世界"
let 🐶🐮 = "dogcow"
세미콜론(Semicolons)
일반적으로는 Swift는 각 구문 후의 세미콜론(;)은 필수조건이 아니지만, 여러 구문을 한 줄에 사용할 경우에는 세미콜론을 필수로 작성해야 합니다.
let cat = "🐱"; print(cat)
// Prints "🐱"
정수(Integers)
정수(Integers)는 부호가 있는 정수(signed)(양수, 0, 음수) 또는 부호가 없는 정수(unsigned)(양수, 0)이 있습니다.
Swift는 8, 16, 32, 64 비트 형태의 부호가 있는 정수와 부호가 없는 정수를 지원합니다. 이러한 정수는 8-bit 부호가 없는 정수는 UInt8, UInt32 등의 네이밍 형태를 가집니다.
정수 범위(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
타입 별칭(Type Aliases)
타입 별칭은 이미 존재하는 타입을 다른 이름으로 정의합니다. typealias 키워드를 사용하여 정의할 수 있습니다.
typealias AudioSample = UInt16
var maxAmplitudeFound = AudioSample.min
// maxAmplitudeFound is now 0
부울 (Booleans)
Swift는 Bool 이라 불리는 기본 부울 (Boolean) 타입이 존재합니다.
let orangesAreOrange = true
let turnipsAreDelicious = false
if turnipsAreDelicious {
print("Mmm, tasty turnips!")
} else {
print("Eww, turnips are horrible.")
}
// Prints "Eww, turnips are horrible."
let i = 1
if i {
// this example will not compile, and will report an error
}
let i = 1
if i == 1 {
// this example will compile successfully
}
튜플 (Tuples)
튜플(Tuples)는 여러 값을 단일 복합 값으로 그룹화 합니다. 튜플안에 값은 어떠한 타입도 가능하며 서로 같은 타입일 필요는 없습니다.
아래 예제의 (404, "Not Found")는 HTTP 상태 코드를 나타내는 튜플입니다.
let http404Error = (404, "Not Found")
// http404Error is of type (Int, String), and equals (404, "Not Found")
위 튜플의 타입은 (Int, String)입니다. 그러므로 아래처럼 별도의 상수 또는 변수로 분해(decompose)하여 정의할 수 있습니다.
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"
또는 0에서 시작하는 인덱스를 사용하여 튜플의 개별 요소 값에 접근할 수 있습니다.
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"
옵셔널 (Optionals)
값이 없는 경우에는 옵셔널을 사용합니다.
옵셔널은 2가지가 존재합니다. 지정된 타입의 값이 있고, 누락될 수 있는 값이 있습니다.
누락될 수 있는 값의 예시로 String의 변수를 Int 값으로 변환하는 초기화가 있습니다. 일부 문자열만 정수로 변환할 수 있습니다. 아래 예제처럼 문자열 "123"은 숫자값 123으로 변환할 수 있지만, 문자열 "hello, world"는 변환할 숫자값이 없습니다.
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// The type of convertedNumber is "optional Int"
위의 코드에서 초기화가 실패할 수 있으므로 Int가 아닌 optional Int 타입인 Int? 타입을 반환합니다.
nil
옵셔널 변수에 특수한 값 nil로 지정하여 값이 없는 상태를 나타낼 수 있습니다.
var serverResponseCode: Int? = 404
// serverResponseCode contains an actual Int value of 404
serverResponseCode = nil
// serverResponseCode now contains no value
아래처럼 기본값 없이 옵셔널 변수를 정의하면 이 변수는 자동적으로 nil로 설정됩니다.
var surveyAnswer: String?
// surveyAnswer is automatically set to nil
옵셔널 바인딩 (Optional Binding)
옵셔널 바인딩은 옵셔널이 값을 포함하고 있는지 확인하고 값이 있는 경우 해당 값을 임시 상시 또는 변수로 사용할 수 있게 해줍니다. if, guard, while 구문에서 옵셔널에 값이 있는지 체크하고 단일 동작의 일부로 상수 또는 변수로 추출할 수 있습니다.
if 구문에서 옵셔널 바인딩은 아래와 같이 사용합니다.
if let <#constantName#> = <#someOptional#> {
<#statements#>
}
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"
대체값 제공 (Providing a Fallback Value)
?? 연산자를 통해 값이 nil일 경우 대체값을 제공할 수 있습니다.
let name: String? = nil
let greeting = "Hello, " + (name ?? "friend") + "!"
print(greeting)
// Prints "Hello, friend!"
강제 언래핑 (Force Unwrapping)
프로그래머의 에러 또는 원치 않는 상태와 같은 실패를 nil로 표현하려면 옵셔널 값에 느낌표(!)를 추가하여 접근할 수 있습니다.
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
let number = convertedNumber!
guard let number = convertedNumber else {
fatalError("The number was invalid")
}
암시적으로 언래핑된 옵셔널 (Implicitly Unwrapped Optionals)
옵셔널은 상수 또는 변수가 "값이 없음"의 가능성을 알려줍니다. 때로는 옵셔널이 값을 처음 설정한 이후에 항상 값을 갖는 것을 보장할 때가 있을 수 있습니다. 이러한 경우 항상 값이 있다고 가정할 수 있으므로 접근할 때마다 옵셔널의 값을 확인하고 언래핑할 필요가 없습니다.
이러한 경우를 위해 언래핑 된 옵셔널 (Implicitly unwrapped optionals)를 제공합니다. 옵셔널을 만들기 위해 타입 뒤에 물음표 (String?)을 작성하는 대신에 느낌표(String!)로 암시적으로 언래핑 된 옵셔널을 작성하면 됩니다. 사용할 때 옵셔널 이름 뒤에 느낌표를 위치시키는 것보다 선언할 때 옵셔널 타입 뒤에 느낌표를 위치시키는 것이 좋습니다.
let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // Requires explicit unwrapping
let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // Unwrapped automatically
에러 처리 (Error Handling)
프로그램이 실행되는 동안 에러가 발생할 때 처리하기 위해 에러 처리(error hadling)를 사용합니다.
값의 존재 유무를 사용하여 함수의 성공 또는 실패를 전달할 수 있는 옵셔널과 달리 에러 처리를 사용하면 에러 원인을 판별하고 필요한 경우 에러를 프로그램의 다른 부분으로 전파할 수 있습니다.
함수에 에러 조건이 되면 에러가 발생하게 됩니다. 해당 함수의 호출자는 에러를 포착하고 적절하게 대응할 수 있습니다.
func canThrowAnError() throws {
// this function may or may not throw an error
}
함수는 선언 뒤에 throws 키워드를 붙이면 에러가 발생할 수 있음을 나타낼 수 있습니다. 에러가 발생할 수 있는 함수를 호출할 때는 표현식 앞에 try 키워드를 붙여야 합니다.
Swift는 catch 절에 의해 처리될 때까지 현재 범위에서 에러를 자동으로 전파합니다.
do {
try canThrowAnError()
// no error was thrown
} catch {
// an error was thrown
}
do 구문은 에러를 하나 이상의 catch 절로 전파할 수 있는 새로운 범위를 만듭니다.
아래는 에러 처리를 사용하여 다양한 에러 조건에 응답하는 방법의 예시입니다.
func makeASandwich() throws {
// ...
}
do {
try makeASandwich()
eatASandwich()
} catch SandwichError.outOfCleanDishes {
washDishes()
} catch SandwichError.missingIngredients(let ingredients) {
buyGroceries(ingredients)
}
위의 예시에서 makeSandwich() 함수는 에러를 발생시킬 수 있으므로 try 표현식으로 래핑됩니다. 함수 호출을 do 구문으로 래핑하면 어떠한 에러도 catch 절로 전파됩니다.
에러가 발생하지 않으면 eatSandwich() 함수가 호출됩니다. SandwichError.outOfCleanDishes 에러가 발생하면 washDIshes() 함수가 호출됩니다. SandwichError.missingIngredients 에러가 발생하면 catch 패턴에 의해 캡쳐된 String 값과 함께 buyGroceries(_:) 함수가 호출됩니다.
References
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/aboutswift
Documentation
docs.swift.org