10. 옵셔널
//: Playground - noun: a place where people can play
//값이 있을 수도 있고 없을 수도 있음을 나타낸다.
//변수나 상수 등에 꼭 값이 있다는 것을 보장할 수 없다.(변수 또는 상수의 값이 nil일 수도 있다.)
import UIKit
//1
var myName: String = "kim do do"
//오류 nil은 String 타입에 할당 될 수 없다.
//myName = nil
//2
//nil은 옵셔널로 선언된 곳에서만 사용될 수 있다.
//옵셔널 변수의 선언 및 nil 할당
var yourName: String? = "kang do"
print(yourName) //Optional("kang do")
yourName = nil
print(yourName) //nil
//3
//옵셔널은 어느 상황에 사용해야 하나?
/* 우리가 만든 함수에 전달되는 전달인자의 값이 잘못된 값일 경우 제대로 처리하지 못했음을 nil을 반환하여 표현*/
//4
//원시 값을 통한 열거형 초기화 100 p
//let primary = School(rawValue: "유치원")
//let graduate = School(rawValue:"석박사")
//let one = Numbers(rawValue:1) //one
//let three = Numbers(rawValue:3) //nil
/* 설명:이 예제에서는 데이터 타입을 명시하지 않고 타입 추론 기능을 사용했다. 이유는 nil을 할당하는 경우가 생기기 때문이다.
컴파일러는 primary, graduate 상수의 데이터 타입을 school? 이라고 추론했을 것이다.
이때 원시 값이 열거형의 case에 해당하지 않으면 열거형 인스턴스 생성에 실패하여 nil을 반환한다.
*/
//5 옵셔널 열거형의 정의
public enum Optional<Wrapped> : ExpressibleByNilLiteral {
case none
case some(Wrapped)
public int(_ some: Wrapped)
// 중략
}
//설명: 옵셔널은 제네릭이 적용된 열거형이다. ExpressibleByNilLiteral 프로토콜을 따른다.
// 옵셔널은 값을 가지는 케이스와, 그렇지 못한 케이스 두가지로 정의되어 있다.
// nil일 때는 none 케이스가 되고, 값이 있느 경우에는 some 케이스가 된다.(옵셔널에 값이 있으면 some의 연관값인 wrapped에 값이 할당 된다.)
// 6
// 옵셔널 자체가 열거형이기 때문에 옵셔널 변수는 switch 구문을 통해 값이 있고 없음을 확인 할 수 있다.
func checkOptoinalValue(value optionalValue: Any?){
switch optionalValue{
case .none:
print("옵셔널 변수는 nil입니다.")
case .some(let value):
print("value is \(value)")
}
}
//7 switch를 통한 옵셔널 값의 확인
let numbers: [Int?] = [2, nil, -4, nil, 100]
for number in numbers{
switch number {
case .some(let value) where value < 0:
print("negative value \(number)")
case .some(let value) where value > 10:
print("large value!!\(value)")
case .some(let value):
print("value \(value)")
case .none:
print("nil")
default:
break
}
}
//결과
//value 2
// nil
//negative value! -4
//nil
// large value!! 100
//8
//옵셔널 추출: 열거형의 some 케이스로 숨어 있는 옵셔널의 값을 옵셔널이 아닌 값으로 추철하는 법
//두 가지 ( 강제추출, 바인딩)
//1. 강제 추출(옵셔널의 값을 강제 추출하려면 옵셔널 값의 두에 느낌표! 를 붙여주면 값을 강제로 추출해서 반환한다. 지양해야함..)
var name: String? = "dongsoo"
//옵셔널이 아닌 변수에는 옵셔널 값이 들어갈 수 없다! 그래서 추출해서 할당해줘야 한다.
var me: String = name!
name = nil
me = name! //런타임 오류(강제 추출시 옵셔널에 값이 없다면, 즉 nil이라면 런타임 오류가 발생한다)
//if 구문을 이용해서 조금 더 안전하게 처리 할 수 있다.
if name != nil {
print("my name is \(name)")
}else{
print("my name == nil")
}
//myName == nil
//2. 옵셔널 바인딩은 옵셔널에 값이 있는지 확인할 때 사용한다.
// 만약 옵셔널에 값이 있다면 옵셔널에서 추출한 값을 일정 블록 안에서 사용할 수 있는 상수나 변수로 할당해서 옵셔널이 아닌 형태로 사용할 수 있도록 한다.
var hisName: String? = "silver"
//옵셔널 바인딩을 통한 임시 상수 할당
if let nname = hisName {
print("his name is \(nname)")
} else {
print("myname == nil")
}
//결과:his name is silver
//옵셔널 바인딩을 통한 임시 변수 할당
if var nnnmae = hisName {
nnnmae = "gold" //변수이므로 내부에서 변경가능
print("his name is \(nnnmae)")
}else{
print("his name == nil")
}
//결과:his name is gold
//옵셔널 바인딩을 사용한 여러 개의 옵셔널 값의 추출
var herName: String? = "green"
var ourName: String? = nil
//friend에 바인딩 되지 않으므로 실행되지 않는다. nil 이라서
if let name = herName, let friend = ourName {
print("we are friend")
}
ourName = "world"
if let name = herName, let friend = ourName {
print("we are friend \(name), \(friend)")
}
//암시적 추출 옵셔널
//때때로 nil을 할당하고 싶지만, 옵셔널 바인딩으로 매번 값을 추출하기 귀찮거나 로직상 nil때문에 런타임 오류가 발생하지 않을 것 같다는 확신이 들때,
//nil을 할당해줄 수 있는 옵셔널이 아닌 변수나 상수가 있으면 좋다. 이때 사용하는 것이 암시적 추출 옵셔널 이다.
//옵셔널을 사용하고자 뒤에 ?를 붙였지만, 암시적 추출 옵셔널을 사용하려면 타입 뒤에 느낌표를 ! 사용해 주면 된다.
var thiereName: String! = "gilbert"
print(thiereName) // gilbert
thiereName = nil
//암시적 추출 옵셔널도 옵셔널이므로 당연히 바인딩을 사용할 수 있다.
if var name2 = thiereName {
print("thiere name is \(name2)")
} else{
print("thiere name == nil")
}
//thiere name == nil
//thiereName.isEmpty // 오류
//옵셔널을 사용할때는 강제적 추출, 암시적 추출 옵셔널을 사용하는 것 보다 옵셔널 바인딩, nil 병합 연산자를 비롯해
//뒤에서 배울 옵셔널 체이닝 등의 방법을 사용하는 편이 훨씬 안전하다.
'ios 뽀개기 > 스위프트 정리' 카테고리의 다른 글
swift http 통신 get방식 post 방식 - 일단 기록 (0) | 2018.06.13 |
---|---|
11. 클래스와 구조체 (0) | 2017.12.04 |
9. 연산자의 종류 (0) | 2017.11.15 |
8. 열거형 (0) | 2017.11.15 |
7. 튜플 배열 딕셔너리 셋 (복습) (0) | 2017.11.14 |
댓글