Optional : 값이 "있을 수도 있고, 없을 수도 있다"
let optionalConstant: Int? = nil
let someConstant: Int = nil
// Nil cannot initialize specified type 'Int'
OPtional의 존재 이유
: nil의 가능성을 명시적으로 표현
// someOptionalParam can be nil
func someFunction(someOptionalParam:Int?){
// ...
}
// someParam must not be nil
func someFunction(someParam:Int){
// ...
}
someFunction(someOptionalOaram:nil)
someFunction(someParam:nil) // 에러:Nil is not compatible with expected argument type 'Int'
아래 코드는 주석을 제외한 위 같은 코드이다.
Optional이 있으면 주석이 없어도 전혀 문제가 되지 않는다.
func someFunction(someOptionalParam:Int?){
// ...
}
func someFunction(someParam:Int){
// ...
}
someFunction(someOptionalOaram:nil)
someFunction(someParam:nil) // 에러:Nil is not compatible with expected argument type 'Int'
enum Optonal<Wrapped> : ExpressibleByNilLiteral{
case none
case some(Wrapped)
}
let optionalValue:Optional<Int> = nil
let optionalValue:Int? = nil
var optionalValue: Int! = 100
switch optionalValue{
case .none:
print("This Optional variable is nil")
case .some(let value):
print("Value is \(value)")
}
//기존 변수처럼 사용 가능
optionalValue = optionalValue +1
// nil 할당 가능
optionalValue = nil
// 잘못된 접근으로 인한 런타임 오류 발생
optionalValue = optionalValue +1 // nil 값을 넣어서 런타임 에러 발생
var optionalValue: Int? = 100
switch optionalValue{
case .none:
print("This Optional variable is nil")
case .some(let value):
print("Value is \(value)")
}
// nil 할당 가능
optionalValue = nil
// 기존 변수처럼 사용불가 - 옵셔널과 일반 값은 다른 타입이므로 연산불가
optionalValue = optionalValue + 1
Optional Binding - 옵셔널 바인딩
Force Unwrapping - 강제 추출
func printName ( _ name : String){
print(name)
}
var myName:String? = nil
printName(myName)
// 전달 되는 값이 nil 이기 대문에 컴파일 오류 발생
위와 같이 nil체크를 하지 않는 다면 에러가 발생할수 있다.
이런 경우에 if-let or if-var으로 nil 체크를 할수 있다.
1개만 바인딩
func printName(_ name: String){
print(name)
}
var myName : String! = nil
if let name: String = myName {
printName(name)
} else {
print("myName == nil)
}
// name 상수는 if-let 구문 내에서만 사용가능하다.
// 상수 사용범위를 벗어났기 때문에 컴파일 오류 발생
printName(name)
1개이상 바인딩
var myName : String? = "yagom"
var yourName: String? = nil
if let name = myName , let friend = yourName {
print("\(name) and \(friend)")
}
// yourName이 nil 이기때문에 실행되지 않는다.
// 예시에서 처럼 1개 이상의 nil 값이 있는 경우 해당 line은 실행 되지 않는다.
yourName = "haha"
if let name = myName , let friend = yourName {
print("\(name) and \(friend)")
}
// yagom and haha
바인딩에 대한 나의 생각
바인딩은 nil을 체크하는 조건문과 비슷한것 같다.
func printName(_ name: String){
print(name)
}
var myName : String? = "Yagom"
printName(myName) // 에러 : (error message)optional로 감싸져있다! 포장 벗겨내고 사용해라!
printName(myName!) // Yagom . '!' 를 붙이면 포장을 강제로 벗길수 있다.
// 만약 선언할때 '!'느낌표 옵션으로 넣으면 옵션을 사용하는데 벗겨서 반환한다라는 의미이다.
// 아래 코드는 위 코드와 동일하다.
func printName(_ name: String){
print(name)
}
var myName : String!
myName="Yagom"
printName(myName)
두가지 방식은 순서의 차이인것 같다.
옵션을 사용할때 벗기는 첫번째 방식과, 번긴다음 할당하는 두번째 방식
myName = nil
print(myName!) // 강제추출시 값이 없으므로 런타임 오류 발생
var yourName: String! = nil // 선언할 때부터 옵션을 벗겨서 전달할 계획이기 때문에 nil '!' 느낌표를 사용했음!
printName(yourName)
// nil 값이 전달되기 때문에 런타임 오류 발생
강제 추출 방식은 추천하는 방식은 아니다. 안전하게 옵셔널을 사용하려면 binding 방식을 사용하는게 좋다.
출처 : 유튜브 "yagom"