var a: Int = 10
var b: Int
print(a)
print(b) // error 발생!
// 값이 없어 접근하면 에러 발생. -> 오류를 제거해주기 위해선 옵셔널 타입으로 선언해야 함!
var b: Int? // 옵셔널 타입
print(b) // nil 출력
옵셔널 타입이라는 새로운 타입임!
Int -> Int?
이때 Int? 는 옵셔널 정수형 타입으로 Int라는 정수형 타입 + nil 형태를 임시값으로 둘러싼 형태 (Enum타입)
*nil은 실제 값이 없는 것이 아니고, "값이 없음을 의미한다"고 한단계 쌓여있는 것
nil : 값이 없음을 표현하는 키워드.
다른 언어에서는 null이라고 많이 표현 (스위프트에서는 실제 값이 없는것이 아님)
옵셔널은 포장지를 한번 둘러싸고 있는 형태라고 생각하면 된다. 따라서 옵셔널을 벗겨서 사용해야 함.
이때 옵셔널을 벗기는 것을 Unwrapping이라고 함.
1) Int (정수형)
-5, -4, -3, -2, -1, 0, 1, 2 ...
2) Int? (옵셔널 정수형) : 포장지로 덮은 형태
[(-5, -4, -3, -2, -1, 0, 1, 2 ...) + nil] // 여기서 [], ()는 이해를 돕기위해 표현한 것으로 코드와는 연관 x
Int, Int?는 서로 다른 타입!!
1) 옵셔널 타입은 값이 없는 경우(nil)를 포함하는 타입. (값이 반드시 있어야 하는 경우, 값이 없으면 에러발생!)
2) 옵셔널 타입과 Non-optional은 서로 다른타입
ex) Double, Double? // 서로 다른 타입!
ex) String, String? // 이것도 마찬가지로 다른 타입!!
옵셔널은 열거형으로 선언되어 있음
Int?
-case Int
-case nil
이렇게 두 부분으로 나누어져 있는 것. 즉 Int?는 Int와 nil을 포함하고 있는 더 큰 원이라고 생각!
// Int? 는 Int를 포함하고 있는 더 큰 원이라고 생각
// 따라서 Int -> Int?로는 변환이 가능하지만, Int? -> Int 로 변환해 줄 때에는 특별한 조치가 필요
var num: Int = 5
Optional(num) // Int타입을 Int? 타입으로 변환하기
print(Optional(num)) // Optional(5)가 출력
옵셔널 타입(임시 타입)을 추출하는 방법 4가지 + 옵셔널 체이닝
nil이 아닌 값이 있다는 것을 확신하고 강제로 값을 추출
num!
자주 사용 x
if문을 통해 nil이 아님을 확인 후, 강제 추출
if num != nil {
print(num!)
}
보통 옵셔널 바인딩 사용
바인딩(상수나 변수에 대입)이 되는 경우에만 특정 작업 진행
if let name = optionalName {
print(name)
}
일반적인 경우
옵셔널 표현식 뒤에 기본값을 제시해서 옵셔널의 가능성을 없앰
optioalName??"홍길동"
디폴트 값 제시 가능한 경우
표현 자체가 옵셔널의 가능성이 있다는 것을 표현. 체이닝의 결과는 항상 옵셔널
human?.choco?.name
Unwrapping 후 사용
var name: String! = "Cody"
// Non-optional 타입의 변수가 저장될 때, 값이 있는 경우 자동으로 값이 추출되어 저장되는 타입
// 제한적인 상황에서 추출될 준비가 되어있는 타입
제한적인 경우, 암묵적으로 추출
옵셔널(String?)타입과 동일하다고 생각해도 무방.
실제 앱 (스토리보드와 Outlet 연결 시 주로 활용)
// 함수에서 옵셔널 타입 파리미터의 사용
// 함수의 정의
func doSomePrint(with label: String, name: String? = nil) {
// 옵셔널 타입 선언과 기본값 설정 -> 함수의 파라미터가 옵셔널 타입일 수 있음
print("\(label): \(name)")
}
doSomePrint(with: "레이블", name: "Cody")
doSomePrint(with: "레이블") // 옵셔널 타입이기에 nil도 허용. 함수 사용시 아규먼트 자체를 생략하는 것도 가능