오늘은 Optional의 사용법?이라기보단 Optional을 어떻게 벗기고 우리가 원하는 data로 사용할 수 있는지 그 방법에 대해서 알아보자.
우선 Optional
에 대해서 간단하게 알아보자.
(자세한건 여기서 볼 수 있다.)
Optional
은 값이 있을수도~ 없을수도~ 있는 경우에 사용한다.
값이 없다는 것은 nil
을 의미한다.
Swift는 이런 Optional을 통해 프로그램의 안정성을 높인다.
Optional
타입임을 알리기 위해 타입 이름 뒤에 ?
을 붙여서 표시한다.
Swift에서 Optional
과 non-Optional
타입은 엄연히 다르게 취급된다.
그렇다면 우리는 Optional
타입인 어떤 프러퍼티에서 value를 가져다 사용하고 싶다.
어떻게 사용할 수 있는지 확인해보자.
Optional
값을 강제로 추출하려면 옵셔널 값 뒤에 !
를 붙인다.
이 경우는 확실하게 Optional
을 벗길 수 있지만 해당 프로퍼티에 값이 없다면 오류를 반환한다.
forcedUnwrapping
에 !
을 사용해서 강제 추출했다.
첫번째 print()
에서는 forcedUnwrapping
이 nil
값이 아니기 때문에 정상적으로 0이 출력되는 것을 확인할 수 있다.
두번째 print
에서는 forcedUnwrapping
가 nil
값이기 때문에 오류가 발생하는 것을 확인할 수 있다.
public var unsafelyUnwrapped: Wrapped {
get {
if let x = self {
return x
}
_debugPreconditionFailure("unsafelyUnwrapped of nil optional")
}
}
if let
을 사용해 self
를 바인딩한다.
값이 있다면 반환하고 없다면 런타임에러를 발생시킨다.
var number: Int? = 3
number.unsafelyUnwrapped // 3
number = nil
number.unsafelyUnwrapped // 런타임 에러 발생
number! // number.unsafelyUnwrapped 와 같습니다.
직접 unsafelyUnwrapped를 호출할 수도 있다.
옵셔널 바인딩은 if
혹은 guard
문을 사용할 수 있다.
if
를 사용한 옵셔널 바인딩은 값이 있는지 확인하고 해당 값을 임시 변수(상수)에 할당해서 사용하는 기법이다.
if
문에서 생성한 임시 상수는 if
문 내부에서만 사용할 수 있다.
guard
를 사용한 옵셔널 바인딩은 guard
문에 있는 조건이 false
인 경우는 else
로 진입하고, true
인 경우에는 guard
문 아래의 코드가 진행된다.
guard
문으로 생성한 상수는 guard
구문 아래에서는 함수 내부의 지역 상수처럼 사용할 수 있다.
guard
문의 else
안에는 return
, break
, continue
, throw
가 포함되어야 한다.
즉, guard
문의 조건이 false
인 경우는 더이상 아래의 코드를 실행하지 않는다.
Optional Binding에 대해서 더 궁금하다면 여기로!
??
을 사용한다.
값이 있는 경우는 옵셔널을 벗긴 값을 반환하고, 없는 경우에는 default 값을 설정할 수 있다.
binding
프로퍼티가 nil
이 아닌 경우에는 프로퍼티의 value가 출력되고, nil
인 경우에는 우리가 지정한 default 값이 출력되는 것을 확인할 수 있다.
public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T)
rethrows -> T {
switch optional {
case .some(let value):
return value
case .none:
return try defaultValue()
}
}
optional
타입이 열거형으로 구현되어 있어 switch-case
문으로 값이 있을 때와 없을 때를 나눠 구현한다.
연산자의 왼쪽에 위치할 인자에 값이 존재한다면 그 값을, 존재하지 않는다면 defatulValue
크로저를 실행해 기본값을 반환한다.
var number: Int? = 3
print(number ?? 0) // 3 출력
number = nil
print(number ?? 0) // number 의 값이 없으므로 기본값 0 출력
Optional Chaining
의 결과는 항상 Optional
이다.
Optional Chaining
에 포함된 표현식 중 하나가 nil
이라면 표현식을 중단하고 nil을 반환한다.
wonhee
는 Optional 타입이 아니므로 name
프로퍼티에 접근시 ?
없이 접근 가능하다.
wonhee2
는 Optional 타입으로 name
프로퍼티에 접근시 ?
가 필요하다.
이때 옵셔널 체이닝했다고 한다.
옵셔널 체이닝의 결과는 항상 옵셔널이므로 두번째 출력도 Optional
로 출력됨을 확인할 수 있다.
이번에는 Address
라는 구조체를 만들고, Person
에 Optional 타입을 갖는 address
프로퍼티를 정의했다.
위의 예제와 다른 점을 찾아보자면
wonhee
에서 address
의 si
를 가져올 때 ?
가 생겼다.
Person
구조체에 address
가 Optional
타입으로 선언되어 있어서 옵셔널 체이닝으로 가져와야 한다.
옵셔널 체이닝의 결과는 항상 옵셔널 이므로 출력 결과도 옵셔널이다.
wonhee2
는 Optional
타입인 Person
이므로 ?
가 2개인 것을 확인할 수 있다.
옵셔널 체이닝시 포함된 표현식 중 하나가 nil
이라면 표현식을 중단하고 nil
을 반환한다고 했다.
wonhee2
의 address
는 nil
이므로 출력 결과가 nil
이다.
오늘은 Optional
을 어떻게 벗기는지 알아봤다.
방법은 여러 가지이고 각자의 특징과 결과가 다르니 이를 잘 알고 상황에 맞게 쓰는게 중요할거 같다.
그럼 이만👋