[Swift] Optional

임승섭·2023년 5월 12일
0

Swift

목록 보기
2/35

기본 개념

var yourName : String
print(yourName)			// 선언만 하고, 값을 초기화하지 않았는데 접근하려고 하면 에러가 발생한다

이럴 때 앱이 종료되지 않도록 옵셔널(Optional)이라는 개념을 도입한다

var yourName : String?	// 변수에 '임시값(nill)'을 넣는다.

어떤 타입에 물음표(?)를 붙인 걸 옵셔널 타입이라고 한다.
Int : 정수형
Int? : 옵셔널 정수형
: ...-3, -2, -1, 0, 1, 2, 3, ... + nill
Int와 Int?는 다른 type이다.
Optional 타입과 Non-optional 타입은 서로 다른 타입이다

nill : 실제 값이 없는 게 아니고, "값이 없음을 표현하는 키워드이다.

단점
포장지(임시적인 타입)로 싸고 있는 느낌이기 때문에
실제 값을 사용하려면, 포장지를 한 번 벗겨주어야 한다.
이 때, nill일 때 벗겨서 사용하려고 하면 그 안에는 값이 없기 때문에 에러가 난다


var num : Int? = 3
var yourAge : Int? = nill		// nill로도 초기화할 수 있다
num = nill

var yourAge = nill (X)			// 무슨 옵셔널 타입인지 추론할 수가 없다

정식문법

let num1 : Int? = 2				// 간편한 방법
let num2 : Optional(Int> = 0	// 정식 문법

주의

let optionalStr : String? = nill	// 잘못된 구문
// nill로 선언하면, 값이 변할 가능성을 주어야 하는데, let을 이용해서 상수로 선언하면 아무 의미가 없어진다
// optional type nill은 항상 변수로 사용한다
var optionalStr : String? = nill

값 복사

var a : Int? = 2
var b = a
// b의 타입은 Optional<Int>
// print(b) : Optinoal(2)

var c = Int = 5
var b = c
// 이렇게 하면 b에 c의 값을 담을 수는 있지만, 타입이 바뀌게 된다. 
// print(b) : Optional(5)

연산 불가능

var num1 : Int? = 3
var num2 : Int? = 7

//print(num1 + num2) -> 에러.

포함관계

  • Int? 안에 Int가 있다고 이해하자
  • Int를 Int?로 담을 수 있다
  • Int?를 Int로 사용하려면 특별한 조치(포장지 벗기기)가 필요하고, nill이 아닌 경우에만 사용 가능하다

추출 방법

4가지 방법 + 옵셔널 체이닝(Chaining)

var num : Int?
var str : String? = "Hi"

// print(num) : nill
// print(str) : Optional("Hi")

강제 추출 (Forced Unwrapping)

  • 안에 값이 있다는 것이 확실할 때 사용한다
print(str!) : "Hi"
print(num!) -> 에러

nill 확인 후 강제 추출

  • if문으로 nill 아니라는 것 확인 후, 강제로 벗긴다
if str != nill {
	print(str!)
}

if num != nill {
	print(num)
}

옵셔널 바인딩

  • 바인딩이 된다면, 특정 작업을 하겠다
if let s = str {	
	print(s)
}
  • str이 새로운 상수에 담긴다면( == nill값이 아니라면) 조건문 내부를 실행한다
    str이 nill이면, 이걸 s에 담을 수 없다
  • 여기서 s의 type은 그냥 String이다
var optionalName : String? = "홍길동"

if let name = optionalName {
	print(name)
}

func doSomething(name : String) {
	guard let name = optionalName else { return }
    print(name)
}

(=)

func doSomething(name : String?) {			// 옵셔널 타입을 input으로 받을 수도 있다
	guard let n = name else { return }		// * guard문 안에서 선언한 변수는 그 밖에서도 사용 가능하다!! 동일한 scope로 취급한다
    print(n)
}
  • if var 또는 guard var 도 사용 가능하지만, 일반적으로 let을 이용한다

Nill-Coalescing

  • nill-coalescing이라는 연산자를 사용한다
  • coalescing : 더 큰 덩어리로 합친다
var serverName : String? = "홍길동"		// Optional("홍길동")

var userName = serverName ?? "미인증사용자" 	// 기본값(디폴트값)을 지정해준다
// 값이 있으면 그 값을 사용하고, nill이 들어있다면 "미인증사용자"를 사용하겠다
// -> nill이 나올 수가 없다!!

var hello = "인사하겠습니다. " + (str ?? "Say, Hi")
// 인사하겠습니다 "Hi"

삼항연산자를 이용한 풀이

var userName = (serverName != nill) ? serverName : "미인증사용자"

함수와 옵셔널

func doSomePrint(with label : String, name : Strint? = nill) {	// 기본값으로 nill을 설정해둔다
	print("\(label) : \(name)")
}

doSomePrint(with : "레이블", name : "스티브 잡스")
doSomePrint(with : "레이블")	//nill로 기본값을 설정해두었기 때문에 쓰기가 편하다.

0개의 댓글