[Swift] Optional
Swift Optional Type
옵셔널
- 스위프트의 특징 중 하나인 안정성을 문법으로 담보하는 기능
- 타입을 선언하고 값이 없으면 에러가 나는데 옵셔널 타입은 값을 넣지 않아도 nil이라는 임시 값이 들어가기 때문에 자주 활용
옵셔널 타입
let num1: Int? = 2 // 간편 표기
let num2: Optional<Int> = 2 // 정식 문법
옵셔널은 nil이거나 nil이 아닌 값만 가질 수 있다.
- nil : 값이 할당되지 않아 오류가 발생했을 때
- nil 아닌 값 : 오류가 발생하지 않았을 때 반환하려는 값이 옵셔널로 래핑된 형태의 값
Int (정수형 타입) / Int? (옵셔널 정수형 타입) / Double (실수형) / Double? (옵셔널 실수형 타입)
-> 각각 서로 다른 타입이다.
nil은 실제로 값이 없는 것은 아니고 값이 없음을 표현하는 키워드
실제로 값이 없는 다른 언어의 null과는 실제로 값이 없는 것이 아니라서 다른 것
var num1: Int = nil // 에러
var num2: Int? = nil
// nil을 넣는다고 해도 옵셔널 타입은 타입 추론으로 자동으로 할당되지않아서 지정 해 줘야 한다.
var optionalNum : Int?
print(optionalNum) // nil
-> 옵셔널 타입끼리는 계산이 불가능하기 때문에 값을 추출해 주어야 한다.
옵셔널 값을 추출하는 방법
1. 강제로 값을 추출
var optionalNum: Int? = nil
optionalNum = 10
print(optionalNum) // Optional(10)
print(optionalNum!) // 10
//느낌표를 붙여주면 강제로 옵셔널을 벗김
- 값이 있다는 것이 확실할 때 사용
- nil로 초기화가 되어있을 때 강제로 추출하면 에러가 남
2. if문으로 nil이 아니라는 것을 확인 한 후, 강제로 벗기기
if str != nil {
print(str!)
}
3 옵셔널 바인딩 (if let 바인딩)
- 바인딩이 된다면, 특정 작업을 하겠다는 의미
- 가장 많이 사용되는 방법
if let s = str {
print(s)
}
func doSomething(name: String?) {
guard let n = name else { return }
print(n)
}
doSomething(name: "hello")
실제로 앱을 만들때는 guard let 바인딩 패턴을 많이 사용
4 닐 코얼레싱 연산자를 사용하는 방법
- 옵셔널 타입에 대하여, 디폴트 값을 제시할 수 있을 때 사용
- 직접 값을 벗겨서 사용하는 것이 아니고, 디폴트 값 제시를 통해 옵셔널 가능성을 없애는 방법
var serverName: String? = "홍길동"
var userName = serverName ?? "미인증사용자" // String타입
//nil인 경우 “미인증사용자”를 출력
optionalName != nil ? optionalName! : "홍길동"
//삼항연산자를 이용한 풀이
옵셔널 체이닝
- 옵셔널타입에 대해, 접근연산자를 사용할때, ?(물음표)를 붙여서, 앞의 타입이 값이 nil을 가질 수도 있음을 표시
- 결과는 항상 옵셔널타입으로 리턴
- 옵셔널 체이닝 과정에서 그 값 중 하나라도 nil을 리턴한다면, 이어지는 표현식을 평가하지 않고 nil 리턴
- 옵셔널 타입을 함수 파라미터로 사용
func doSomePrint(with label: String, name: String? = nil) { // String? = nil
print("\(label): \(name)")
}
doSomePrint(with: "레이블", name: "스티브 잡스")
doSomePrint(with: "레이블", name: nil)
doSomePrint(with: "레이블")
// 모두 에러없이 실행 됨
- 헷갈릴 수 있는 부분
// 함수
Dog?.sit?()?.name
// Dog?.sit? -> 함수가 없을 수도 있다는 뜻
// Dog?.sit?()? -> 함수의 결과값이 없을 수도 있다는 뜻
// 딕셔너리
books?["Apple"]?.name
// books? -> 딕셔너리가 없을 수도 있다는 뜻
// books?["Apple"]? -> 딕셔너리의 결과값이 없을 수도 있다는 뜻
- 옵셔널 타입에 접근해서 사용하는 함수는 앞의 타입을 벗기지 않아도 사용 가능
(함수 자체가 옵셔널 타입은 아니기 때문에 함수를 벗겨서 사용할 필요 없음)- 함수가 리턴형이 없는 경우
- 타입에 값이 있으면 함수 실행
- 타입에 값이 없으면 nil
- 함수가 리턴형이 있는 경우
- 타입에 값이 있으면 옵셔널 리턴 타입으로 반환
(원래 리턴형 옵셔널이 아니어도) - 타입에 값이 없으면 nil로 반환
- 타입에 값이 있으면 옵셔널 리턴 타입으로 반환
- 함수가 리턴형이 없는 경우
IUO(Implicitly Unwrapped Optional)
- 옵셔널 묵시적 추출
- 굉장히 많이 사용되는 방식
- 이 개념은 추후에 다시 다루도록 함