소피it블로그

[Swift 공식문서] The Basics 정리 (7) - Optionals 본문

개발_iOS/스위프트

[Swift 공식문서] The Basics 정리 (7) - Optionals

sophie_l 2022. 5. 14. 09:34

https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html

 

The Basics — The Swift Programming Language (Swift 5.6)

The Basics Swift is a new programming language for iOS, macOS, watchOS, and tvOS app development. Nonetheless, many parts of Swift will be familiar from your experience of developing in C and Objective-C. Swift provides its own versions of all fundamental

docs.swift.org

값이 비어있을 수도 있는 경우 옵셔널을 쓴다. 옵셔널은 1) 값이 있어서 옵셔널을 언래핑함으로써 해당 값에 접근할 수 있거나 2) 값이 아예 없거나 두 가지의 경우가 있다.

예를 들어 스위프트의 Int 타입은 문자열로 된 숫자 값을 정수 값으로 변경해줄 수 있는 이니셜라이저가 있다. 그렇지만 정수 123으로 변환이 가능한 문자열 "123"과 달리 문자열 "hello world"는 정수로 변환할 수 없다. 이렇듯 이니셜라이저가 실패할 수도 있기 때문에 Int가 아닌 옵셔널 Int가 반환된다. 옵셔널 Int는 Int?라고 쓰는데, 물음표는 해당 상수 / 변수가 옵셔널이며, Int 값을 가질 수도 있고 아무 값도 가지지 않을 수도 있음을 알려준다(그러나 불리언 값이나 문자열 값 등 다른 값은 가질 수 없다).

 

1. nil

 

  • optional이 아닌 상수, 변수와 함께 쓸 수 없다. 쓸 상수, 변수가 특정 조건 하에 값이 없게 되는 상황이라면 반드시 옵셔널로 선언해야 한다.
  • 디폴트 값 없이 옵셔널 변수를 선언하게 되면 해당 변수에는 자동으로 nil값이 부여된다.
var surveyAnswer: String?
// surveyAnswer is automatically set to nil

2. If Statements and Forced Unwrapping

 

  • 옵셔널에 값이 있는지 확인하기 위해서 ==나 !=와 함께 if statement를 써줄 수가 있다.
  • 옵셔널에 값이 있다는 확신이 있다면 옵셔널 이름의 끝에 느낌표(!)를 더함으로써 해당 값에 접근해줄 수 있다. 이를 forced unwrapping이라고 한다.
if convertedNumber != nil {
    print("convertedNumber has an integer value of \(convertedNumber!).")
}
// Prints "convertedNumber has an integer value of 123."

3. Optional Binding

 

  • 옵셔널 바인딩: 옵셔널에 값이 있는지를 확인하기 위해서, 또 값이 있다면 해당 값을 일시적인 상수나 변수로 쓸 수 있게 해주기 위해 사용한다.
  • if나 while과 함께 써줌으로써 옵셔널 안에 값이 있는지 확인하고 해당 값을 상수나 변수로 추출해줄 수 있다.
  • if와 함께 옵셔널 바인딩을 사용해주는 경우의 예시
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"
  • 옵셔널 바인딩에는 상수와 변수를 모두 사용할 수 있다. 변수로 사용할 경우 if let 대신에 if var로 써주면 됨
  • 하나의 if statement 안에 다양한 옵셔널 바인딩과 불리언 조건을 추가할 수 있다. 컴마로 구분한다. 이 경우 옵셔널 바인딩에서 단 하나의 값이라도 nil이 나오거나 불리언 조건 중 하나라도 거짓이면 if문 전체가 false로 판명된다.
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"
  • if와 함께 사용한 optional binding의 상수나 변수는 if문 안에서만 사용할 수 있는 반면, guard와 함께 사용한 옵셔널 바인딩에서는 상수나 변수가 guard문 뒤에 나오는 코드에서 사용할 수 있다.

4. Implicitly Unwrapped Optionals

 

  • 때로는 프로그램 구조상 옵셔널에 값이 있다는 확신을 할 수가 있다. 이런 경우에는 매번 옵셔널에 값이 있는지 확인하고 언래핑하는 과정을 생략하는 게 도움이 된다. 이런 경우의 옵셔널을 implicitly unwrapped optionals라고 한다.
  • implicitly unwrapped optionals는 옵셔널로 만들고 싶은 타입의 뒤에 ?가 아닌 !를 붙임으로써 생성한다. 예를 들면 String?이 아닌 String! 옵셔널을 사용할 때 옵셔널의 이름에 !를 붙이는 대신 옵셔널을 선언할 때 옵셔널의 타입 뒤에 !를 붙인다는 점을 기억하자.
  • implicitly unwrapped optionals는 주로 클래스 이니셜라이저에서 사용된다.
  • implicitly unwrapped optionals는 옵셔널이지만 매번 값을 언래핑할 필요 없이 옵셔널이 아닌 값처럼 사용될 수 있다.
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
  • 스위프트는 implicitly unwrapped optionals을 우선 일반적인 옵셔널 값처럼 사용하려고 하지만, 옵셔널로 사용될 수 없으면 force unwrapping한다. 위의 코드에서 implicitString은 문자열 타입이기 때문에 assumedString이 할당되기 전에 먼저 강제 언래핑되지만, 이하의 코드에서는 optionalString에 explicit한 타입이 지정되어있지 않기 때문에 일반적인 옵셔널로 여겨진다.
let optionalString = assumedString
// The type of optionalString is "String?" and assumedString isn't force-unwrapped.
  • implicitly unwrapped optional이 nil일 때 값에 접근하려고 하면 값이 없는 옵셔널을 강제 언래핑해주는 것과 같이 런타임 에러가 난다.
  • 일반 옵셔널처럼 값이 nil이 아닌지 확인한 후 사용하거나 옵셔널 바인딩을 사용할 수도 있다.
  • 해당 변수가 후에 nil이 될 가능성이 있을 때는 사용하지 말아야 한다.