Optional 옵셔널을 이용하는 이유, 옵셔널 추출 (+열거형enum)

hyein·2022년 8월 14일
0

Swift

목록 보기
4/9
post-custom-banner

학습 내용을 복습하기 위해 야곰님의 스위프트 프로그래밍 교재의 내용을 정리한 것임을 밝힙니다.

옵셔널이란?
값이 있을 수도 있고, 없을 수도 있음을 의미한다.
nil(없음) 표현이 가능함. nil은 다른 언어의 null과 비슷하다고 보면 된다.
String?처럼 타입 뒤에 ?를 붙여 옵셔널임을 나타내거나 Optional<String>이라고 나타내기도 한다.

변수에 nil이 있음을 가정해야하는 이유
1. 내가 만든 함수에 전달되는 전달인자의 값이 잘못된 값일 경우 제대로 처리하지 못했음을 nil을 반환하여 표현할 수 있기 때문
2. 매개변수를 굳이 넘기지 않아도 된다는 뜻으로 매개변수 타입을 옵셔널로 정의할 수 있기 때문

** 열거형 enum: 연관된 항목들을 묶어서 표현할 수 있는 타입(추가, 수정 불가)

  • 쓰임 (3가지)
  • 제한된 선택지를 주고 싶을 때
  • 정해진 값 외에는 입력받고 싶지 않을 때
  • 예상된 입력 값이 한정되어 있을 때
  • 특징
  • 스위프트의 열거형은 항목별로 값을 가질 수도, 가지지 않을 수도 있음
  • 스위프트의 열거형은 각 열거형이 고유의 타입으로 인정됨
  • 열거형 각 항목이 원시값이라는 형태로 (정수, 실수, 문자 타입 등의) 실제 값을 가질 수 있음
  • 원시값을 rawValue로 가져올 수 있음(그렇지 않으면 항목 이름만 출력됨)
  • 일부 항목만 원시값을 줘도 됨
  • 원시값 부여 안 된 항목들이 .rawValue로 호출될 때 String타입은 항목이름이 출력된다. Int타입은 이전 항목이 없을 때는 첫 항목을 기준으로 0부터 1씩 늘어난 값이 출력되고, 이전 항목이 있으면 그것의 원시값+1이 출력된다.
  • 연관값을 사용해 다른 언어에서 공용체라고 불리는 값의 묶음도 구현 가능
enum Student: Int { //Int는 원시값의 타입
  case elementary1 = 8 //elementary1이라는 항목, 원시값 8을 가짐 
  case elementary2 = 9
  case middle1 = 14
  case middle2 = 15
  case middle3 = 16
  case high1 = 17
  case high2 = 18
  case high3 = 19
}
  • 원시값을 통해 열거형 변수 또는 상수 생성도 가능하다. 이때 옵셔널 개념(1)이 필요하다.
let student1 = Student(rawValue: 16) //Optional(tousereadLine.Student.middle3)

Student라는 열거형에 16인 원시값이 있기 때문에 student1이라는 상수를 생성해줄 수 있지만, 만약 열거형에 원시값으로 존재하지 않는 1로 상수를 생성해주려 한다면 nil을 반환하게 된다.
추가적으로, 위의 코드에서는 nil을 할당하는 경우가 생김을 예측할 수 있으므로 타입 추론 기능을 사용했다는 것을 알 수 있다.


옵셔널은 제네릭이 적용된 열거형이다. (제네릭을 공부하면 내용 더 추가하기)

  • 옵셔널은 값을 갖는 케이스(some, 연관값은 Wrapped)와 그렇지 못한 케이스(none) 두 가지로 정의된다.
    //옵셔널은 none과 some이라는 항목을 케이스로 갖는 열거형인 것임.
  • 옵셔널에 값이 있으면 some의 연관값인 Wrapped에 값이 할당된다.
    // 값이 옵셔널이라는 열거형의 방패막에 보호되어 래핑되어 있는 모습임
  • switch 구문으로 매번 값이 있는지 없는지 확인할 수 있지만, 불편하므로 값을 안전하고 편하게 추출하는 방법을 아래에서 알아보자

열거형의 some 케이스로 감싸진 옵셔널의 값을 옵셔널이 아닌 값으로 추출하는 방법

1. 강제추출 (런타임 오류 가능성이 높아 가장 위험) - 옵셔널의 값 뒤에 !
** 옵셔널에 값이 없다면(nil) 런타임 오류 발생하므로 if문을 통해 값이 있는지 미리 확인 후에 !로 값을 추출하는 것이 안전함

var name: String? = "Hana"
var nameForcedExtraction: String = name! 

2. 옵셔널 바인딩 (옵셔널 체이닝 공부하면 내용 추가하기)
if문 조건에 임시 상수를 할당해 값이 있는지 없는지 파악

var myName: String? = "Hana"
if let name = myName { 
	print("My name is \(name)")
} else {
	print("myName == nil")
}

내 생각에는 지역변수 개념과 비슷한 것 같다.
for (int i = 0; i>0 ; i++)에서 횟수 제어 변수를 생성한 것처럼 말이다.

여러 개의 옵셔널 값도 추출해낼 수 있다. ','을 쓰면 된다.
다만, 그 중 하나라도 nil값이면 실행되지 않는다.

var myName: String? = "Hana"
var yourName: String? = "Mina"
if let name = myName, let friend = yourName { 
	print("\(name) & \(friend)")
} // Hana & Mina

3. 암시적 추출 옵셔널
값이 nil이 아닐 것이라는 확신이 있을 때 사용한다. (그치만 이런 순간은 드물다.)
옵셔널을 표시할 때는 타입 뒤에 ?를 붙여주었지만, 암시적 추출 옵셔널을 사용할 때는 !를 붙여주면 된다.
암시적 추출 옵셔널로 지정된 타입은 여전히 '옵셔널'이므로 nil값을 할당해줄 수 있긴 하다.

var myName: String! = "Hana"
post-custom-banner

0개의 댓글