[Swift 문법] 2 - 3. 옵셔널 (Optional Types)

JJOOEE__·2024년 6월 11일
0

Swift 문법

목록 보기
7/13
post-thumbnail

🍏 3. 옵셔널 (Optional Types)

◻️ 1) 옵셔널의 정의

  • Optional은 nil을 사용할 수 있는 타입과 없는 타입을 구분하기 위함이며, nil을 사용할 수 있는 Type을 Optional Type이라 부른다
let name : String?

이렇게 변수를 선언하거나 할 때 타입 뒤 에 붙어있는 ? 물음표가 옵셔널!

-'nil' 이라는 값을 가질 수 있으면 Optional Type이고,
이 Optional Type을 선언할 땐 타입 옆에 ?(물음표)를 붙인다

◻️ 2) nil이란?

  • 값이 없음을 나타내는 특별한 상수, 어떤 변수나 상수가 특정한 값이 없거나 존재하지 않을 때 nil을 사용하여 이를 표현
예시 ) 
let animal = ["name" : "Fubao", "gender" : "female"]
let name = animal["name"]   // "Fubao"
let name = animal["alias"]    //  nil
  • 입력한 키값이 없다고 컴파일 오류를 낼 수는 없고,
    리턴을 안 할 수도 없고, 공백을 리턴 해 줄 수도 없기 때문에 오류가 났다고 알려주는 의미로 이 값을 nil로 출력해 주는 것!

◻️ 3) Non-Optional Type vs Optional Type

  • nil을 저장할 수 있는 건 오로지 Optional로 선언된 자료형만 가능함!!!!!!

🍀 ① Non-Optional Type

  • 값이 항상 존재해야 합니다.
  • nil을 할당할 수 없습니다.
  • 초기화 시 반드시 값을 할당해야 합니다.

예시) //선언과 동시에 초기화 해준 변수(상수),
Type Annotation을 사용해서 사용해온 변수(상수)

var name =  "jjoohee"
var name : String
name = "jjoohee"
var name : String
name = nil   //ERROR 

Non-Optional Type에서 값이 없을 경우 에러가 남

🍀 ② Optional Type

  • Optional Type 선언하기

🌈 ① Type Annotation을 이용하기

  • 자료형(Type)의 뒤에 ?를 붙여주면 됨
var name : String?
var name : String?
name = nil

🌈 ② Type Inference를 이용하기

  • 다음으론 타입 추론을 이용한 방법임
    기존과 같이 선언과 동시에 값을 초기화 해주면 되는데, Optional로 선언, 초기화 되는 값이 무조건 Optional 자료형
let a: Int? = nil
let b =a

옵셔널 타입의 값인 a를 b에다가 선언과 동시에 초기화 해주면

let b = a   //nil

b도 옵셔널 타입으로 선언됨

var alias: String
var name: String?

print(type(of: alias))  // 결과값 : String
print(type(of: name))  // 결과값 : Optional<String>
Optional<String>

의 값을 사용할 땐 옵셔널을 언래핑 해서 사용해야함!!!

◻️ 3) Optional Unwrapping

let a: Int? = nil
print(type(of: a))

  • 그냥 Int 자료형이 아닌, Optional Int 자료형임.
    따라서 Optional 자료형을 사용하기 위해선,
    Optional이란 포장지를 까주고 써야 함

  • 만약 Optional이란 포장지를 제거하지 않는다면?

let a: Int? = nil
a = 4

var myInfo = " 내 나이는 \(a)살 입니다"

이런식으로 출력해보면 내 나이는 Optional(4)살 입니다.

Optional Unwrapping을 하기 위해선
절대 Unwrapping 하고자 하는 변수(상수)가 nil이면 안 된다

🍀 ① 강제 추출(Forced Unwrapping)

  • 옵셔널에 값이 nil인것을 고려하지 않고 그냥 강제로 옵셔널을 벗겨버리는 것
  • 방법 : ! (느낌표)연산자
    • Optional로 선언된 변수(상수)를 사용할 때 그 뒤에 !를 붙여주면 됨

      let a: Int? = nil
      a = 4
      var myInfo = " 내 나이는 \(a!)살 입니다"
      
      // 출력값 : 내 나이는 4살 입니다
    ! 주의 ! 실제 프로그래밍에선 거의 쓸 일 없다 ^^
  • 값이 없어서 nil 일 경우에도 옵셔널을 강제로 해제한다 는 것을 절대 잊으면 안된다!!!!
  • 값이 없을 경우 옵셔널 강제 해제 > 컴파일 에러/런타임 에러

🍀 ② 옵셔널 바인딩(if let vs guard let)

  • 3 가지 Syntax
if let name : Type = OptionalExpression {
}

while let name : Type = OptionalExpression {
}

guard let name : Type = OptionalExpression {
}
  • 옵셔널 표현식을 먼저 평가함
  • 값이 있는 경우(nil이 아닌 경우) 정의된 상수(name)에 옵셔널이 해제된 값을 저장하고 true를 반환함
  • 값이 없는 경우(nil) false를 반환함
  • 타입 추론이 되므로 대부분 Type Annotation 생략

참고로 while을 이용한 방법은 거의 사용되지 않기 때문에, while은 제외하고 알아볼 거임

🌈 ① 옵셔널 바인딩 if let

  • optional타입의 상수 4
let optionalNumber: Int? = 4
  • if let
if let nonOptionalNumber = optionalNumber {
	print(nonOptionalNumber)
 	} else {
 		print(optionalNumber)
 } // 출력값 : 4
  • 만약 nil이 지정된 경우라면?
let optionalNumber: Int? = nil // 출력값은 4
  • 옵셔널 바인딩 if let 매커니즘

    ① 표현식이 nil인지 아닌지 판별하자

    ② 표현식이 nil이 아닌 경우

  • optionalNum의 값이 nil이 아닌 경우,
    optionalNum을 Unwrapping 한 값을 nonOptionalNum에 대입함


    ! 주의 !
  1. nonOptionalNum 이라고 if let을 통해 선언된 상수의 scope는 if 구문임 > if 문 밖에서는 nonOptionalNum이라는 상수에 접근할 수 없음!

  2. nonOptionalNum은 optionalNum을 Unwrapping 한 값을 대입한 것 뿐, optionalNum의 값은 여전히 Optional Type이다!

if let nonOptionalNumber = optionalNumber {
	print(nonOptionalNumber)
    print(optionalNumber)
 } 
 4
 Optional(4) 
 
  • optionalNum을 Unwrapping 한 값이 nonOptionalNum일 뿐, optionalNum은 여전히 Optional Type의 값

    ③ 표현식이 nil인 경우

  • nil인 경우엔 if 구문을 거치지 않고 else 구문으로 빠짐, 당연하게도 nonOptionalNum 이란 상수는 사용할 수 없음

💡. TIP

  • Non Optional Type의 이름
    - 그냥 Optional Type의 이름을 그대로 똑같이 써도 됨

    만약 두 개의 변수가 서로 다른 Scope에서 같은 이름으로 선언된 경우, 실행 시점에서 가까운 곳에 선언된 변수로 선택됨

  • 한번에 여러 개의 옵셔널 타입을 바인딩 할 수도 있음

    • name, age 모두 nil이 아니여야 if구문이 true가 됨


🌈 ② 옵셔널 바인딩 guard let

  • guard문은 특성상 함수(메서드)에서만 쓰이며,
    guard 구문의 조건을 만족하지 못하면 else문으로 빠져서 함수의 실행을 종료 시킬 때 사용함 (return해 버림)
    = "너 이 조건 만족 못하면, 내 함수에서 나가!"
let optionalNumber: Int? = nil

guard let nonOptionalNumber = optionalNumber else {
	//the 'optionalNumber' is nil
    return
}
  • 옵셔널 바인딩 guard let 매커니즘

    ① 표현식이 nil인지 아닌지 판별하자

    ② 표현식이 nil이 아닌 경우

  • guard 문에선 표현식이 nil이 아닐 경우 else 문으로 빠지지 않고, 원래 guard문을 실행시키던 scope로 돌아옴

    NonOptionalNum이라는 Optional이 해제된 값을 guard 구문 밖에서 사용할 수 있음

guard문은 guard문 밖에서 사용 가능함

! 주의 !
옵셔널 바인딩된 nonOptionalNum의 Scope는 guard 구문 밖임
따라서 else문에서는 nonOptionalNum을 사용할 수 없음

③ 표현식이 nil인 경우


이렇게 else 구문으로 빠져서 return을 때리거나 실행을 종료하는 것이 일반적임!

💡. TIP

  • Non Optional Type의 이름

    • guard문은 함수(메서드)의 매개변수로 들어온 표현식에 한해서만 똑같이 쓰는 것 가능함

      • ⭕️ 가능한 경우
        함수(메서드)로 넘어온 파라미터 값 (임시 상수 혹은 변수)을 바인딩 할 경우

      • ❌ 불가능한 경우
        함수(메서드) 내에서 선언한 상수 혹은 변수를 바인딩 할 경우

  • 한번에 여러 개의 옵셔널 타입을 바인딩 할 수도 있음, 옵셔널 바인딩을 하나의 gurad문에서 연속으로 할 수도 있고, condition을 넣을 수 있음


🌈 if let vs guard let 언제 사용할까?

🍏 if let

  • 단순히 옵셔널 처리 값에 대한 피드백만 주고 싶을 때

  • 너 값 있으면 이렇게 처리하고 nil 이면 저렇게 처리해!

🍎 guard let

  • 옵셔널 처리 값이 nil인 경우 무조건 함수의 실행을 종료 시킬 때

  • 너 값 없니? 그럼 내 함수에서 나가

🍀 ③ ?? 연산자 (Nil-Coalescing Operation)

🌈 ?? Syntax

Optional Expression ?? Non-Optional Expression
  • 예제
let name: String? = "Joohee"

자 Optional String Type인 name이 있음

이때,
name이 nil이 아닐 경우 -> hello, (name)

name이 nil일 경우 -> hello, what's your name?

  • 기존 옵셔널 바인딩 이용시
if let name = name {
	print("hello, \(name)")
    } else { 
    	print("hello, what's your name?")
 } 

이렇게 구현 해야함

  • ?? 연산자 이용시
print("hello, " + (name ?? "what's your name?"))

한줄로 연산이 끝나게 됨!!!!

🌈 ?? 매커니즘

① name에 값이 있을 경우

② name에 값이 없을 경우 (nil)

! 주의 !

Nil-Coalescing에 사용되는 Optional Type과 Non-Optional Type은

Optional을 제외하면 동일한 Type이어야 함

  • ex)

    • Optional String Type ?? Non-Optional String Type (O)
    • Optional String Type ?? Non-Optional Int Type (X)

🍀 ④ IUO (옵셔널 묵시적 추출)

-- 이것도 잘 사용하지 않기에.. 필요해지면 더 공부해보고 정리하겠음!

🌈 언제, 왜 사용 하냐면

  • IBOultet사용시 프로퍼티 지연 초기화를 위해 필요!
profile
개발이 어려운 나를 위한... 개발노트

0개의 댓글