08. 옵셔널

JinStory77·2022년 5월 14일
0

Swift 공부_기초

목록 보기
8/11

옵셔널

  • 스위프트의 안전성을 문법으로 담보하는 기능이다.
  • 옵셔널(optional)이란 사전적 의미는 '선택적인', 즉 값이 '있을 수도, 없을 수도 있음'을 나타내는 표현이다.
    • 즉 '변수나 상수 등에 꼭 값이 있다는 것을 보장할 수 없다. 즉, 변수 또는 상수의 값이 nil일 수도 있다.'는 의미
  • 옵셔널과 옵셔널이 아닌 값은 철저히 다른 타입으로 인식하기 때문에 컴파일할 때 오류를 걸러낼 수 있다.


1. 옵셔널 사용

  • '?'를 붙여 표현할 수 있다.
  • 옵셔널 변수 또는 상수가 아니면 nil을 할당 할 수 없다.
  • nil이란?
    • Int 타입의 변수에 0을 할당했다면 값이 없다는 의미가 아니라 '0'이라는 '값'을 넣을 것이다. " "로 빈 문자열을 만들었다면 이 또한 '빈 문자열'이라는 값을 의미하지, 값이 없음을 나타내는 것은 아니다. nil을 정말로 값이 없을 때만 사용한다.
  • 해당 변수 또는 상수에는 값이 없을 수 도 있다. 즉, 변수 또는 상수가 nil일 수도 있으므로 사용에 주의하라로 해석하면 된다.
  • 값이 없는 옵셔널 변수 또는 상수에 접근하려면 런타임 오류가 발생한다.
  • 옵셔널을 사용하는 상황
    • 함수의 전달인자 값이 잘못 된 경우, 제대로 처리 못했음을 nil을 반환하여 표현한다.

  • 오류가 발생하는 nil 할당
var myname: String = "Jin"
myName = nil        // 오류 발생
// nil은 옵셔널로 선언된 곳에서만 사용 가능

  • 옵셔널 변수의 선언 및 nil 할당
var myName: String? = "Jin"
// var myName: Optional<String>과 같음
print(myName)       // 옵셔널 값을 print 함수로 출력하면 Optional("Jin")으로 뜸

myName = nil
print(myName)       // nil

  • 옵셔널 자체가 열거형이기에 옵셔널 변수는 switch 구문을 통해 값이 있고 없음을 확인할 수 있다.
func checkOptionalValue(value optionalValue: Any?){
    switch optionalValue {
    case .none:
        print("This Optional variable is nil")
    case .some(let value):
        print("Value is \(value)")
    }
}

var myName: String? = "Jin"
checkOptionalValue(value: myName)   // Value is Jin

myName = nil
checkOptionalValue(value: myName)   // This Optional variable is nil
let numbers: [Int?] = [2, nil, -4, nil, 100]

for number in numbers {
    switch number {
    case .some(let value) where value < 0:
        print("Negative value!! \(value)")
    case .some(let value) where value > 10:
        print("Large value!! \(value)")
        
    case .some(let value):
        print("value \(value)")
        
    case .none:
        print("nil")
    }
}
// value 2, nil, Negative value!! -4, nil, Large value!! 100


2. 옵셔널 추출

  • 열거형의 some 케이스로 숨어있는 옵셔널의 값을 옵셔널이 아닌 값으로 추출하는 옵셔널 추천(Optional Unwrapping)

2.1. 강제 추출

  • 옵셔널 값의 뒤에 느낌표(!)를 붙여주면 된다.
  • 옵셔널 값을 추출하는 가장 간단하지만 가장 위험한 방법이다.
    • 런타임 오류가 일어날 가능성이 가장 높기 때문이다.
    • 옵셔널을 만든 의미가 무색해지는 방법이다.
    • 강제 추출시 옵셔널에 값이 없다면, 즉 nil이라면 런타임 오류가 발생한다.
    • 런타임 오류의 가능성을 늘 가지고 있기에 강제 추출 방식은 지양해야한다.
var myName: String? = "Jin"

// 옵셔널이 아닌 변수에는 옵셔널 값이 들어 갈 수 없음. 추출해서 할당해줘야 함.
var Jin: String = myName!

myName = nil
Jin = myName!       // 런타임 오류

// if 구문 등 조건문을 이용해 조금 더 안전하게 처리해볼 수 있음
if myName != nil {
    print("My name is \(myName!)")
} else {
    print("myName == nil")
}

2.2. 옵셔널 바인딩

  • if 또는 while 구문 등과 결합하여 사용가능하다.
  • 옵셔널에 값이 있는지 확인할 때 사용한다.
    • 만약 옵셔널 값이 있다면 옵셔널에서 추출한 값을 일정 블록 안에서 사용할 수 있는 상수나 변수로 할당해서 옵셔널이 아닌 형태로 사용할 수 있게 해준다.
var myName: String? = "Jin"

// 옵셔널 바인딩을 통한 임시 상수 할당
if let name = myName {
    print("My name is \(name)")
} else {
    print("myName == nil")
}
// My name is Jin

// 옵셔널 바인딩을 통한 임시 변수 할당
if var name = myName {
    name = "wizplan"    // 변수이므로 내부에서 변경 가능
    print("My name is \(name)")
} else {
    print("myName == nil")
}
// My name is wizplan

2.3. 암시적 추출 옵셔널

  • 옵셔널은 물음표(?)를 사용했지만 암시적 추출 옵셔널은 느낌표(!)를 사용하면 된다.
  • 때때로 nil을 할당하고 싶지만, 옵셔널 바인딩으로 추출하기 귀찮거나 로직상 nil때문에 런타임 오류가 발생하지 않는다는 확신이 들 때 사용한다.
var myName: String! = "Jin"
print(myName)
myName = nil

// 암시적 추출 옵셔널도 옵셔널이므로 당연히 바인딩 사용 가능
if let name = myName {
    print("My name is \(name)")
} else {
    print("myName == nil")
}
// myName == nil

myName.isEmpty    // 오류
profile
Let's smile for future 🤩

0개의 댓글