옵셔널

박형석·2021년 11월 30일
0

Swift

목록 보기
6/20
post-thumbnail
post-custom-banner

Optional?

  • 스위프트의 특징인 안정성을 문법으로 담보하는 기능
  • 값이 있을 수도, 없을 수도 있음을 나타내는 표현
  • 값이 없는 옵셔널 변수 또는 상수에 강제로 접근시 런타임 오류 발생
  • '옵셔널'과 '옵셔널이 아닌 값'은 다른 타입

Nil?

  • 0, "" 둘 다 하나의 값. nil이 아님
  • 변수 또는 상수에 정말 값이 없을 때만 nil로 표현

옵셔널 사용

  • 어떤 값이 잘못된 값일 경우 처리하기 위해서
  • 굳이 넘기지 않도 된다는 뜻으로 사용하기 위해서
  • 등등

옵셔널 구현

옵셔널은 제네릭이 적용된 열거형으로 구현되어 있음

public enum Optional<Wrapped> : ExpressibleByNilLiteral {
 case none
 case some(Wrapped)
 public init(_ some: Wrapped)
 // ...
}
  • 값이 없을 때는 none
  • 값이 있을 때는 some, 연관 값으로 Wrapped가 있다.
  • 즉 값이 옵셔널이라는 열거형에 래핑되어 있는 모습

옵셔널 추출 (Optional Unwrapping)

열거형의 some 케이스로 래핑되어 있는 옵셔널의 값을 옵셔널이 아닌 값으로 추출하는 것

  1. Forced Unwrapping : 위험, 지양, 런타임 오류. 뒤에 !
  2. 암시적 추출 옵셔널 : nil을 할당하고 싶지만 옵셔널 바인딩이 귀찮을 때, 변수 상수 타입의 뒤에 !. nil도 할당할 수 있고 옵셔널이 없는 타입으로 사용할 수 있지만 이것도 지양. 런타임 오류.
  3. Optional Binding
    • 옵셔널에 값이 있는지 확인할 때 사용
    • 있다면, 옵셔널에서 추출한 값을 일정 블록 안에서 사용할 수 있는 항수나 변수로 할당해서 옵셔널이 아닌 형태로 사용할 수 있음. if let ~
    • 옵셔널 체이닝과 환상의 결합
  4. 빠른 종료와 함께 하는 옵셔널 바인딩
    • guard문 : guard 뒤의 조건문이 true 일 때, 코드를 통과, 실행. 예외 사항만 빠르게 처리하려면 guard문이 더 간편, 가독성이 좋다.
    • if let과 같이 guard로 옵셔널을 바인딩 할 수 있고 해당 변수나 상수를 지역 상수처럼 사용할 수 있다.
    • 한계 : guard문은 자신을 감싸는 코드 블록이 제어문 전환 명령어( return, break, continue, throw 등)를 쓸 수 없는 상황이라면 사용이 불가능하다. 또 애시당초 자신을 감싸는 특정 코드블록(함수, 메서드, 반복문 등)이 없으면 사용이 제한된다.

옵셔널 체이닝

중첩된 값을 호출하기 위해 옵셔널을 중첩된 형태(체인)로 사용하는 것

let roomNumber: Int? = person.address?.building?.room?.number
  • 중첩 중에 하나라도 값이 없으면 nil을 반환한다.
  • 모든 옵셔널에 값이 있다면 해당 프로퍼티, 메서드, 서브스크립트 등을 호출할 수 있다.
  • Forced Unwrapping도 할 수 있지만 런타임 오류가 난다.
  • 옵셔널 바인딩과 함께 사용하기
if let roomNumber = person.address?.building?.room?.number {
 print(roomNumber)
} else {
 print("Can not find room number"
}
  • 옵셔널 체이닝에 값 할당하기 및 할당해서 정상적인 값 반환 받기도 가능
// 만약 빌딩에 대한 값이 없었다면, 체인의 위치와 관계없이 값을 넣어주면 바인딩에 값이 들어온다.
person.address?.building = Building(name: "SongWon")

if let roomNumber = person.address?.building?.room?.number {
 print("roomNumber : \(roomNumber)")
} else {
 print("Can not find room number"
}

// roomNumber : 404
  • 메서드도 호출 가능하다.
func fetchFullAdress() -> String? { }
func navigateToPlace() { }

person.address?.navigateToPlace()
person.address?.fetchFullAdress()?.isEmpty
  • 서브스크립트도 호출 가능하다. 다만 옵셔널이 서브스크립트를 사용하고자 할 때는 대괄호보다 앞에 ?를 표기해줘야 한다.
let optionalArray: [Int]? = [1, 2, 3]
optionalArray?[1] // 2

let optionalDictionary: [String:[Int]]? = [String:[Int]]()
optionalDictionary?["numberArray"] = optionalArray
// 딕셔너리의 value의 타입은 [Int]이지만 [Int]?를 넣어줬다. 그래서 ? 을 붙인다. 
optionalDictionary?["numberArray"]?[2] = 3
profile
IOS Developer
post-custom-banner

0개의 댓글