티스토리 뷰

1.Optional 이란??

wrapped 값 또는 없는 nil을 나타내는 있는 타입입니다.

다시말해 값이 있을수도, 없을수도 있음을 알려줍니다.


2.Optional 선언하기

옵셔널을 선언하는 방법은 다음과 같습니다.

let shortForm: Int? = Int("42")
let longForm: Optional<Int> = Int("42")

보통은 Optional<>이라고 쓰기보다는 뒤에 ? 를 붙여서 많이 사용하죠.

어떻게 선언하든 의미는 같습니다.

옵셔널을 명시해 주면 shortForm은 값이 없을 수도 있다,

즉 nil이 들어갈 수 있음을 알려줍니다.

 

언제 사용할까?

 

우선 공식 문서에 있는 예제를 가져왔습니다.

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)

print(convertedNumber)
//Optional(123)

String을 Int로 바꿔주는 예제인데요, 예제의 "123"은 숫자 123으로 변환할 수 있지만

"hello, world"는 Int로 바꿀 수 없죠.  

String에서 Int로의 형변환이 성공할 수도, 실패할 수도 있기 때문에 결과를 Optional로 반환받게 됩니다.

실제로 convvertedNumber를 출력해보면 

Optional(123) 이 출력되는 것을 확인할 수 있습니다.

 

예를 하나 더 들어보겠습니다.

property가 값을 항상 가지고 있다는 것을 보장하지 못할 때 optional을 사용하는 예 입니다.

protocol Pet {
    var name: String? { get set }
    func makeSound()
}

class Person {
    var name: String
    var pet: Pet?
    
    init(named name: String) {
        self.name = name
    }
}

위 코드를 보면 Pet이라는 프로토콜과 Person이라는 클래스가 있죠.

그리고 Persont 클래스 안에서 pet은 옵셔널로 선언되어 있는 것을 볼수 있습니다.

모든 사람이 pet을 가지는 것은 아니고, 또 현재 pet을 가지고 있다고 해서 항상 가지고 있는 것은 아니기 때문이죠.

 

 

2.1 Optional Unwrapping

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)

print(convertedNumber)
//Optional(123)

우리는 convertedNumber를 출력하면 Optional(123)이 나오는 것을 확인 했습니다.

그럼 이 값을 바로 사용할 수 있을 까요?

 

Opional 값에 2를 곱하려고 하면 이런 에러를 볼 수 있습니다.

Int? 타입은 Int로 Unwrapped 해야한다.

 

convertedNumber 값은 Optional 타입이지 Int타입 입니다.

서로 다른 타입이기 때문에 convertedNumber를 Int타입으로 변환해서 사용을 해야합니다.

 

그럼 어떻게 변환해야 할까요??

Optional을 원하는 타입으로 변환하는 과정을 unwrapping. 

옵셔널 값을 언래핑한다라고 말하는데요, 옵셔널을 벗겨내서 우리가 원하는 값을 얻을 수 있습니다.

 

 

2.1.1 ForceUnWrapping

첫번째 방법은 말 강제 언래핑인데요, 말 그대로 강제로 값을 벗겨냅니다.

! 를 사용해서 옵셔널을 벗겨낼 수 있는데, 값이 있다고 보장된 상황에서만 사용하는 것이 좋습니다.

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
print(convertedNumber) //Optional(123)
print(convertedNumber!) //123

 

옵셔널을 벗겨줌으로써 우리가 원하는 곱하기도 수행할 수 있습니다!

let num = 2*convertedNumber!
print(num) //246

 

값이 없는 optional을 강제로 언래핑하게 되면 어떻게 될까요?

let possibleNumber = "hello, world"
let convertedNumber = Int(possibleNumber)

print(convertedNumber!)

옵셔널 값을 언래핑 하는데 nil이라고 에러가 납니다.

 

위에서 값이 있다고 보장된 상황에서만 force Unwrapping을 해야한다고 했는데,

값이 없는 상황에서는 이렇게 런타임 에러를 내주기 때문에 빠뜨릴 염려가 없죠.

 

2.1.2 Optional Binding

옵셔널 바인딩은 옵셔널을 "안전하게" 헤제하는 방법입니다. 

실제로 존재하는지 확인하고 상황에 따라 언래핑된 값을 임시 상수나 변수로 사용할 수 있습니다.

 

if let

if let은 가장 흔하게 사용되는 unwrapping  방법입니다.

struct Cat {
    var name: String?
    var vaccinated = false
    
    func makeSound() {
        print("Meow")
    }
}

var possibleCat: Cat? = Cat()

if let cat = possibleCat {
    cat.makeSound()
}
// Meow

let이라는 상수에 possibleCat을 할당함으로써 옵셔널 값을 추출할 수 있습니다.

값이 nil이 라면 false이기 때문에 if 구문은 수행되지 않습니다.

 

위에서 임시 상수라는 말을 했었는데 말그대로 if let으로 추출된 값은 if 구문을 빠져나가면

사용할 수 없습니다.

 

말 그대로 if 문 안에서만 사용할 수 있는 임시 상수인거죠.

 

하지만 if 구문을 빠져나가서도 계속 사용할 수 있는 방법이 있습니다!

guard let 을 사용하면 됩니다.

 

guard let

사용 하는 방법은 if let 과 비슷합니다.

차이점을 알아보겠습니다.

 

1.우선 guard let은 else 구문이 반드시 있어야 합니다.

값이 nil이 아니라면 코드가 계속 실행되만, 값이 없다면 else 구문이 실행됩니다.

else 를 추가하니 다른 에러를 보여줍니다.

2.else 구문을 탈출하려면 return 또는 throw를 사용해야 한다고 합니다.

return 을 추가했습니다.

또 에러를 보여줍니다. 함수 밖에서는 return 할 수 없다.

3.즉 특정블록 안에서만 실행이 가능하다는 거죠.

 

고양이 소리를 듣는 함수를 하나 만들어 보겠습니다.

func listenCat() {
    guard let cat = possibleCat else {
        return
    }
    cat.makeSound()
}
// Meow

4.guad let 구문 밖에서도 전역변수로 사용이 가능합니다.

 

이렇게 if let과 guard let을 이용하여 옵셔널 바인딩 하는 방법을 알아보았습니다.

 

 

2.2 Optional Chaining

 

3.Optional로 어떤 문제를 해결할 수 있을 까? /언제 Optional을 쓸까?/왜 쓸까?

 

4.Optional은 어떻게 구현되어 있을까?

optional은 enum으로 구현되어 있습니다.

public enum Optional<Wrapped> {
    case none
    case some(Wrapped)
}

값이 없을 때는 .none 있을 때는 .some 두가지 case를 가지고 있습니다.

 enum 이기 때문에 아래처럼도 사용 가능합니다.

var str: String? = nil

if str == .none {
    print("str is nil")
}

if str == nil {
    print("str is nil")
}

그리고 Optional은 제네릭 타입이기 때문에 어떤 타입이든 받을 수 있습니다.

 

+)면접질문

일부의 경우에 우리는 암시적으로 언래핑된 옵셔널을 사용하는 것을 피할 수 없다.

언제그럴까? 왜그럴까?

 

[참고]

https://khawerkhaliq.com/blog/swift-optionals/

https://khawerkhaliq.com/blog/swift-optional-binding/#Conclusion

https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html

https://developer.apple.com/documentation/swift/optional

반응형

'Swift' 카테고리의 다른 글

[Swift]Property Wrapper  (0) 2022.05.03
MVVM in SwiftUI  (0) 2022.03.30
[swift]Closure란? + Closure축약 과정  (0) 2021.11.25
[swift]어노테이션  (1) 2021.10.26
[xcode]fail to prepare for communication with playground for an unknown reason  (0) 2021.10.26
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함