Optional 옵셔널
값이 있을 수도, 없을 수도 있음을
nil이 할당 될 수 있는지 없는지 표현
let optionalConstant: Int? = nil; //옵셔널이라서 nil할당 가능
// let someConstant: Int = nil; - 옵셔널이 아니라서 nil할당안됨 오류발생
func someFunction(someOptionalParam: Int?) { //옵셔널타입 nil가능
// ....
}
func someFunction(someOptionalParam: Int) { //옵셔널 아님 nil 불가능
// ....
}
someFunction(someOptionalParam: nil) //nil가능
// someFunction(someParam: nil) //nil불가능
옵셔널을 쓰는 이유
명시적 표현
1. nil의 가능성을 코드만으로 표현가능
2. 문서/주석 작성 시간 절약
안전한 사용
1. 전달받은 값이 옵셔널이 아니라면 nil 체크를 하지 않고 사용가능
2. 예외 상황을 최소화 하는 안전한 코딩
3. 효율적 코딩
옵셔널 문법과 선언
옵셔널 문법 = enum + generics 열거형 + 제너럴
(수업 후반에 다시 배울거에요)
옵셔널 선언
enum Optional<Wrapped>: ExpressibleByNiliteral {
case none
case some(Wrapped)
}
let optionalValue: Optional<Int> = nil
let optionalValue: Int? = nil
옵셔널 표현
- 느낌표(!)를 이용한 암시적 추출 옵셔널
- 물음표(?)를 이용한 옵셔널
var implicitlyUnwrappedOptionalValue: Int! = 100 // Int!
switch implicitlyUnwrappedOptionalValue { //열거형
case .none: //값이 없으면
print("This Optional variable is nil")
case .some(let value): //값이 들어오면
print("Value is \(value)")
}
// 기존 변수처럼 사용 가능 - 값이 101
implicitlyUnwrappedOptionalValue = implicitlyUnwrappedOptionalValue + 1
// nil 할당 가능
implicitlyUnwrappedOptionalValue = nil
// 잘못된 접근으로 인한 런타임 오류 발생 - nil을 넣었는데 옵셔널밸류에 접근하려니까 오류발생
//implicitlyUnwrappedOptionalValue = implicitlyUnwrappedOptionalValue + 1
기존 변수처럼 사용 가능
nil 할당 가능
nil을 넣었는데 옵셔널밸류에 접근하려면( + 1하려고) 오류발생
var optionalValue: Int? = 100 //Int? 인트가 들어있을 수도 있고 없을 수도 있음
switch optionalValue {
case .none:
print("This Optional variable is nil")
case .some(let value):
print("Value is \(value)")
}
// 기존 변수처럼 사용불가 - 옵셔널과 일반 값은 다른 타입이므로
//optionalValue = optionalValue + 1
// nil 할당 가능
optionalValue = nil
기존 변수처럼 사용불가 (옵셔널과 일반 값은 다른 타입)
nil 할당 가능
옵셔널 추출 optional unwrapping
옵셔널에 들어있는 값을 사용하기 위해 꺼내오는 것
옵셔널 방식
1. 옵셔널 바인딩
2. 강제 추출( 사용하지않겠노라 다짐하기 )
func printName(_ name: String) {
print(name)
}
var myName1: String? = nil
//printName(myName1)
// 전달되는 값의 타입이 다르기 때문에(String /= String?) 컴파일 오류발생
if let name: String = myName { // name 상수는 if-let 구문 내에서만 사용가능
printName( name )
} else {
print("myName == nil")
}
// printName(name)
// 상수 사용범위를 벗어났기 때문에 컴파일 오류 발생
var yourName: String! = nil
if let name: String = yourName {
printName(name)
} else {
print("yourName == nil")
}
myName = "ony"
yourName = nil
if let name = myName, let friend = yourName {
print("\(name) and \(friend)")
}
// yourName이 nil이기 때문에 실행되지 않습니다
yourName = "hana"
if let name = myName, let friend = yourName {
print("\(name) and \(friend)")
}
// ony and hana
옵셔널에 값이 들어있는지 아닌지 확인하지 않고 강제로 값을 꺼내는 방식,
만약 값이 없을경우(nil) 런타임 오류가 발생하기 때문에 추천되지 않는다.
var myName: String? = "ony"
printName(myName!) // ! 로 r 값을 강제로 가져오기
myName = nil
//print(myName!)
// 강제추출시 값이 없으므로 런타임 오류 발생
var youName: String! = nil // 암시적 추출 옵셔널
yourName = nil
//printName(yourName)
// nil 값이 전달되기 때문에 런타임 오류발생
예제
var optionalA: Int? = nil
var optionalB: Int! = nil
optionalA = 100
optionalB = optionalA // ! nil인 값에 ? nil값 넣기 가능 !
// optionalA = optionalB + 1 오류발생
// print(optionalB * 3) 오류발생 안에 nil임
! nil인 값에 ? nil값 넣기 가능하다