-
Swift Optional 정의, 옵셔널 추출 방법Swift 2022. 12. 22. 22:59
Optional
옵셔널은 wrapping 된 값으로 optional이 선언 되어있는 값은 내부에 값이 있는 지 없는지 알 수 없음아래처럼 두가지 방식으로 선언이 가능한데, 문서에 따르면 코드를 쉽게 읽고 쓸 수 있도록 축약형(Int?)이 선호된다고 함!
let long: Optional<Int> let short: Int?
❓어떤 경우에 사용할 수 있을까?
먼저 타입에 대한 개념이 필요하다. 타입은 메모리 공간에 어떤 형태로 어떤 데이터가 들어있다고 알려주는 것임!
아래의 예시처럼 값을 저장하지 않고 출력을 하면 에러가 생긴다. 값을 출력 하기전에 값을 저장해줘야한다.
변수 선언시에 값을 넣어주거나 따로 넣어주거나 아래에 포함된 주석처럼 값을 저장해줘야 에러가 발생하지 않는다.var myAge: Int //var myAg: Int = 20 //myAge = 20 print(myName)
위의 예시처럼 메모리 공간에 값이 없으면 에러가 발생하는데 옵셔널은 메모리 공간에 새로운 타입을 정의하고 에러가 나지 않도록 임시 타입을 넣어서 실제로 값이 없음을 걸러주는 역할을 한다고 보면된다.
💡간단히 optional 정수형 타입의 배열과 , 정수형 타입의 배열의 모양(?)을 이해해보자!
정수형 배열은 배열내에 정수 값들만 담고 있고(1,2,3,4) ,
옵셔널 정수형 배열은 값이 없는 경우(nil)을 포함(1,2,3,4, +nil)한다는 것으로 이해하면서 아래와 같이 예시를 들어볼 수 있다!var numbers: [Int] = [1, 2, 3, 4] var optionNumbers: [Int]? = [1, 2, 3, 4] print(numbers) //[1,2,3,4] print(optionNumbers) //Optional([1, 2, 3, 4])
❓왜 사용하는가
- 내가 만든 함수에 전달되는 인자값이 잘못된 값일 경우 안전하게 nil을 반환하여 표현 하기 위함.
- nil일수도 있다는 부분을 문서화 하지 않아도 코드만으로도 표현할 수 있음.
❓optional 타입과 정수형 타입의 값을 비교하면 어떻게 될까?
var numbers: [Int] = [1, 2, 3, 4] var optionNumbers: [Int]? = [1, 2, 3, 4] print(numbers) //[1, 2, 3, 4] print(optionNumbers) //optional[1, 2, 3, 4] print(numbers == optionNumbers) //true
optional타입의 배열과 정수형 타입의 배열은 다른데 어떻게 true라는 값이 나오는지 optional은 알면 알수록 어렵고 신기하다…
그 이유는 값을 비교 하기전에 옵셔널이 아닌 값이 옵셔널로 wrapping되기 때문optional before the comparison is made. The constant is wrapped as an optional before comparing. 이라고 https://github.com/apple/swift/blob/main/stdlib/public/core/Optional.swift#L371
설명된 부분을 참고하면 좋을 것 같다.
💡옵셔널 값 추출 하는 방법
기본적으로 옵셔널은 값을 가지는 케이스(some)와 값을 가지지 못하는 케이스(none)로 정의 되어있음!
아래의 예시를 참고해보자! 값이 있으면 some케이스, 없으면 none케이스로 아래와 같이 switch문을 사용해서 구분할 수 있다.
let studentsName: [String?] = ["sehong", "hbang", "kio", nil] for student in studentsName { switch student { case .some(let name) where name == "sehong": print("학생 1은 sehong입니다.") case .some(let name) where name == "hbang": print("학생 2는 hbang입니다.") case .some(let names): print("나머지는 \\(names)입니다.") case .none: print("존재하는 학생이 없습니다.") } } //학생 1은 sehong입니다. //학생 2는 hbang입니다. //나머지는 kio입니다. //존재하는 학생이 없습니다.
하지만 하나의 옵셔널 값을 switch구문을 통해서 값이 있는지 없는지 케이스를 나눠가며 확인하면 번거로움!
그래서 간단하게 추출 하는 방법에 대해서 알아보자!
옵셔널 바인딩
if let
특징은 if let 구문 내에서만 상수가 사용 가능하다. 사용된 scope를 벗어나면 if let에서 사용한 상수가 출력되지 않음var number: Int? number = 1004 if let myNumber = number { print("if let: \\(myNumber)") }else { print("myNumber is nil") }
guard let
함수나 반복문 등 특정 블록 내부에 위치하지 않으면 사용이 제한.
if let과 달리 guard let상수는 선언된 블록 내부에서는 사용 할 수 있음.
예외사항만을 처리하고 싶다면 guard 구문을 사용하는 것이 훨씬 간편.func checkNumber() { var number: Int? number = 1004 print(number) guard let myNumber = number else { print("myNumber is nil") return } print("guard let: \(myNumber)") } checkNumber()
Nil-Coalescing Operator (nil 병합 연산자)
Nil코어레싱 연산자의 경우에는 ‘??’를 사용한다!
아래와 같이 studentName[0]배열의 값이 있으면 해당 인덱스의 값을 출력하고 값이 없으면 연산자 ?? 뒤의 값이 출력된다.let studentsName: [String?] = ["sehong", "hbang", "kio", nil] let studentOne = studentsName[0] ?? nil print(studentOne) //Optional("sehong") let studentFour = studentName[3] ?? "There is no student" print(studentFour) //There is no student
Forced Unwrapping(강제 추출)
Optional로 선언된 상수나 변수에 값이 있다고 확신이 되면 ‘!’을 변수나 상수 뒤에 붙여서 무조건 강제로! 언래핑을 할 수 있음!let policeNumber: Int? = 112 print(policeNumber!) //112 let fireStationNumber: Int? fireStationNumber = nil print(fireStationNumber!) //런타임 에러 발생 출력안됨!
옵셔널 체이닝
옵셔널에 속해 nil일지도 모르는 프로퍼티나 메서드 등을 가져오거나 호출할 때 사용할 수 있음!
아래와 같이 호출하고 싶은 변수나 상수 뒤에 ‘?’를 붙여서 표현할 수 있다.let myFriendList = ["sehong" : "bestFriend", "hbang" : "justFriend", "nalee" : "Friend"] if myFriendList?.hasPrefix("best") == true { print("My bestfriend is sehong") } //My bestfriend is sehong
🏷️ 참고 도서 : 야곰 스위프트 프로그래밍5
🏷️ 참고 사이트 :https://developer.apple.com/documentation/swift/optional
https://github.com/apple/swift/blob/main/stdlib/public/core/Optional.swift
'Swift' 카테고리의 다른 글
Dictionary init(uniqueKeysWithValues:) (0) 2023.01.06 Swift 구조체와 클래스 3 저장 속성, 지연 저장 속성, 계산 속성, 타입 속성, 프로퍼티 감시자 (0) 2023.01.04 Swift 구조체와 클래스 2 초기화(Initialization) (0) 2022.12.30 Swift 구조체와 클래스 1(Struct and Class) 사용이유, 공통점, 차이점, 구조체와 클래스 내의 let, var 선언 (0) 2022.12.28 API Design Guidelines 알아보기(swift Naming) (0) 2022.12.21