옵셔널

Gooreum·2021년 10월 28일
0

Swift

목록 보기
10/16
post-custom-banner

정의

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

옵셔널 사용

  • nil은 옵셔널로 선언된 곳에서만 사용될 수 있다. 옵셔널 변수 또는 상수 등은 데이터 타입 뒤에 물음표(?)를 붙여 표현해준다.
var myName: String? = "Mingu"
print(myName) // Mingu

myName = nil
print(myName) // nil이 출력됨, myName변수를 옵셔널로 선언했기 때문에 nil이 되어도 컴파일 오류가 발생하지 않음.
  • 옵셔널은 열거형으로 구현되어 있다.
    • 옵셔널은 제네릭이 적용된 열거형이며, 옵셔널이 값을 갖는 케이스와 그렇지 못한 케이스 두 가지로 정의되어 있다.
    • 즉, nil일 때는 none 케이스가 될 것이고, 값이 있는 경우는 some 케이스가 되는데, 연관 값으로 Wrapped가 있다.
    • 따라서 옵셔널에 값이 있으면 some의 연관 값인 Wrapped에 값이 할당된다. → Wrapping되어 있는 옵셔널 값은 바로 사용할 수 없음.
    • 옵셔널 추출을 통해 Unwrapping 해야만 값을 사용할 수 있다.
public enum Optional<Wrapped> : ExpressibleByNilLiteral {
    case none
    case some(Wrapped)
    init(_ some: Wrapped)
    ///중략
}
  • 옵셔널 자체가 열거형이기 때문에 옵셔널 변수는 switch 구문을 통해 값이 있고 없음을 확인할 수 있다.

  • 여러 케이스의 조건을 통해 검사하고자 한다면 where 절과 병합해서 사용하면 좋다.

(예제는 생략)

옵셔널 추출

  • 열거형 some 케이스로 꼭꼭 숨어 있는 옵셔널의 값을 옵셔널이 아닌 값으로 추출하는 옵셔널 추출(Optional Unwrapping)에 대해 알아보자.

강제추출

  • 옵셔널 강제 추출(Forced Unwrapping) 방식은 옵셔널의 값을 추출하는 가장 간단하지만 가장 위험한 방법이다.
    • 런타임 오류가 일어날 가능성이 가장 높으며, 사실상 옵셔널을 만든 의미가 무색해지는 방법이기도 하다.
  • 옵셔널 강제추출은 옵셔널 값의 뒤에 느낌표(!)를 붙여주면 강제로 값을 추출하여 반한받게 된다. 그런데 옵셔널에 값이 없다면, 런타임 오류가 발생한다.
  • 되도록 이 방법은 지양하자!
  • 암시적 추출 옵셔널과 헷갈릴 수가 있으나, 강제추출은 옵셔널 값 뒤에 (!)를 붙이는 것이고, 압시적 추출 옵셔널은 타입뒤에 (!)를 붙이는 것!
    var myName: String? = "Mingu"
    var yourName: String! = "Swift"
    
    [강제추출]
    print(myName!)
    [암시적 추출]
    print(myName)

옵셔널 바인딩

  • 옵셔널 바인딩은 옵셔널에 값이 있는지 확인할 때 사용한다.
    • 만약 옵셔널에 값이 있다면 옵셔널에서 추출한 값을 일정 블록 안에서 사용할 수 있는 상수나 변수로 할당해서 옵셔널이 아닌 형태로 사용할 수 있도록 해준다.
  • 옵셔널 바인딩은 if 또는 while 구문 등과 결합하여 사용할 수 있다.
    var myName: String? = "Mingu"
    //myName이 nil인지 아닌지만 확인하기 위한 용도.
    if let _ = myName {
    
    }
    
    //옵셔널 바인딩을 통한 임시 상수 할당
    if let myName = myName {
    	print("My Name is \(myName)")
    } else {
    	print("myName == nil")
    }
    
    //My Name is Mingu
    
    //옵셔널 바인딩을 통한 임시 변수 할당
    if var name = myName {
    	name = "wizplan"
    	print("My name is \(name)")
    } else {
    	print("myName == nil")
    }
    //My name is wizplan
  • 옵셔널 바인딩을 통해 한 번에 여러 옵셔널의 값을 추출할 수도 있다.
    • 쉼표(,)를 사용해 바인딩 할 옵셔널을 나열하면 된다.

    • 단, 바인딩하려는 옵셔널 중 하나라도 값이 없다면 해당 블록 내부의 명령문은 실행되지 않는다.

      var myName: String? = "Mingu"
      var yourName: String? = nil
      
      //friend에 바인딩이 되지 않으므로 실행되지 않음.
      if let name = myName, let friend = yourName {
      	print("We are friend! \(name) & \(friend)")
      }
  • 옵셔널 바인딩은 옵셔널 체이닝과 환상의 결합을 이룸.

암시적 추출 옵셔널

  • 타입 뒤에 느낌표(!)를 사용해주면 된다.
  • 여전히 옵셔널이기 때문에 nil도 할당해줄 수 있으나, nil이 할당되면 런타임 오류가 발생할 가능성이 있음.
  • 되도록이면 지양하자.
profile
하루하루 꾸준히
post-custom-banner

0개의 댓글