yujjne 2024. 3. 8. 19:08

값이 μ—†μŒμ„ ν¬ν•¨ν•˜λŠ” μ˜΅μ…”λ„μ˜ κ°œλ…μ— λŒ€ν•΄ ν•™μŠ΅ν•œ λ‚΄μš©μ„ μ •λ¦¬ν•΄λ³΄κ³ μž ν•œλ‹€.

 

β˜‘οΈμ˜΅μ…”λ„

Swiftμ—μ„œλŠ” λ³€μˆ˜λ₯Ό μ €μž₯ν•˜λŠ” 곡간에 λ°•μŠ€λ₯Ό μ”Œμ›Œλ†“λŠ”λ‹€!

μ§„μ§œ λ°•μŠ€λŠ” μ•„λ‹ˆκ³  였늘 배울 μ˜΅μ…”λ„μ— λŒ€ν•œ λΉ„μœ λ₯Ό 듀어본건데

빈 값은 μ»΄ν“¨ν„°μ—κ²ŒλŠ” μžˆμ–΄μ•Ό ν•  것이 μ—†λ‹€! πŸš¨λŠ” λŠλ‚Œμ΄κΈ° λ•Œλ¬Έμ— μ—λŸ¬λ₯Ό λ°œμƒμ‹œν‚€κ³  μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ’…λ£Œμ‹œν‚€κΈ°λ„ ν•œλ‹€.

λ•Œλ¬Έμ— μ΄λ ‡κ²Œ λͺ¨λ“  λ³€μˆ˜μ— λ°•μŠ€λ₯Ό μ”Œμ›Œλ†“κ³  μ €μž₯을 ν•˜λ©΄ 값이 μžˆμ„ λ•Œμ™€ 없을 λ•Œ λͺ¨λ‘ μ•ˆμ „ν•˜κ²Œ 컴퓨터가 값을 읽을 수 μžˆλ‹€ πŸ˜ƒ

 

 

 

  • 값이 없을 수 μžˆλŠ” μƒν™©μ—μ„œ μ˜΅μ…”λ„(Optional)을 μ‚¬μš©ν•©λ‹ˆλ‹€.
  • μ˜΅μ…”λ„μ€ λ¬ΌμŒν‘œ ? λ‘œ λ‚˜νƒ€λƒ…λ‹ˆλ‹€. (νƒ€μž… μ–΄λ…Έν…Œμ΄μ…˜)
  • μ˜΅μ…”λ„μ€ 두 가지 κ°€λŠ₯성을 λ‚˜νƒ€λƒ…λ‹ˆλ‹€.
    • 값이 있고 μ˜΅μ…”λ„λ‘œ λž˜ν•‘(wrapping)해놓은 값을 μ–Έλž˜ν•‘(unwrapping)ν•˜μ—¬ ν•΄λ‹Ή 값에 μ•‘μ„ΈμŠ€ν•  수 μžˆλ‹€.
    • 값이 μ „ν˜€ μ—†λ‹€.
  • μ˜΅μ…”λ„ νƒ€μž…λΌλ¦¬μ˜ 연산은 λΆˆκ°€λŠ₯
  • μ˜ˆμ‹œ μ½”λ“œ
// μΆ•μ•½ νƒ€μž… ν‘œν˜„
var serverResponseCode: Int? = 404 
// 정식 νƒ€μž… ν‘œν˜„
var myPetName: Optional<String> = "멍멍이"

func pay(with card: String?) {
   // κ΅¬ν˜„ μ½”λ“œ
}

// μ˜΅μ…”λ„ νƒ€μž…λΌλ¦¬μ˜ 연산은 λΆˆκ°€λŠ₯
var num1: Int? = 4
var num2: Int? = 2

num1 + num2 // μ—λŸ¬ λ°œμƒ!

let optionalString1: String? = "Hello, "
let optionalString2: String? = "world!"

// μ˜΅μ…”λ„ String 값듀을 μ—°κ²°ν•˜λ €λŠ” μ‹œλ„
let result = optionalString1 + optionalString2 // μ—λŸ¬ λ°œμƒ!

 

μ˜΅μ…”λ„μ˜ ꡬ쑰

(μ°Έκ³ ) optional은 λ‚΄λΆ€μ μœΌλ‘œ enum의 ꡬ쑰λ₯Ό 가지며 nil을 κ°€μ§€λŠ” noneκ³Ό μ‹€μ œ 값을 κ°–λŠ” some으둜 κ΅¬μ„±λ˜μ–΄ μžˆλ‹€.

 

β˜‘οΈ nil ν• λ‹Ή

  • λ³€μˆ˜μ— nil을 ν• λ‹Ήν•¨μœΌλ‘œμ¨ 값이 μ—†λŠ” μƒνƒœμ˜ μ˜΅μ…”λ„ ν”„λ‘œνΌν‹°λ₯Ό λ§Œλ“€ 수 μžˆλ‹€.
  • μ˜ˆμ‹œ μ½”λ“œ
var serverResponseCode: Int? = 404
serverResponseCode = nil

var surveyAnswer: String?
// surveyAnswer λŠ” μžλ™μœΌλ‘œ nil 둜 μ„€μ •λœλ‹€.

 

μ˜΅μ…”λ„ 값에 nil ν• λ‹Ή κ°€λŠ₯ν•˜λ©° 값을 μ•ˆ λ„£μœΌλ©΄ μžλ™μœΌλ‘œ nil μ„€μ •λœλ‹€!

 

β˜‘οΈ μ˜΅μ…”λ„ 바인딩

  • μ˜΅μ…”λ„ν•˜κ²Œ μ„ μ–Έν•œ νƒ€μž…μ˜ μ˜΅μ…”λ„μ„ λ²—κΈ°λŠ” κ³Όμ • ex) - Int? → Int, String? → String
  • μ˜΅μ…”λ„ 바인딩은 μ˜΅μ…”λ„ 값이 λΉˆκ°’μΈμ§€ μ‘΄μž¬ν•˜λŠ”μ§€ κ²€μ‚¬ν•œ ν›„, μ‘΄μž¬ν•˜λŠ” 경우 κ·Έ 값을 λ‹€λ₯Έ λ³€μˆ˜μ— λŒ€μž…μ‹œμΌœ λ°”μΈλ”©ν•˜λŠ” 것을 의미
  • μ΄λ ‡κ²Œ 빈 값을 μ²΄ν¬ν•˜κ³  μ˜΅μ…”λ„ 값을 μ–Έλž˜ν•‘ ν•΄μ£ΌλŠ” 것은 κ°•μ œλ‘œ μ–Έλž˜ν•‘ν•˜λŠ” 것보닀 훨씬 μ•ˆμ „ν•˜λ‹€.
  • if let/if var, guard let/guard var을 μ¨μ„œ μ˜΅μ…”λ„ 값을 μΆ”μΆœν•΄ μƒˆλ‘œμš΄ λ³€μˆ˜μ— λ°”μΈλ”©ν•œλ‹€.
  • if let vs guard let μ°¨μ΄μ 
    • if let은 if문의 μ½”λ“œ κ΅¬ν˜„λΆ€ λ‚΄μ—μ„œλ§Œ μƒμˆ˜ μ‚¬μš©μ΄ κ°€λŠ₯(지역 λ³€μˆ˜)
    • guard let μ€ guard문을 ν†΅κ³Όν•œ μƒμˆ˜λ₯Ό guardλ¬Έ λ°–μ—μ„œ μ‚¬μš©μ΄ κ°€λŠ₯(μ „μ—­λ³€μˆ˜)
  • μ˜ˆμ‹œ μ½”λ“œ

if let/ if var: { } μ•ˆμ—μ„œ μ‚¬μš©ν•  λ³€μˆ˜λ₯Ό μ •μ˜ν•˜κ³  nil이 아닐 κ²½μš°μ—λ§Œ 블둝 λ‚΄λΆ€μ—μ„œ λ³€μˆ˜μ— 접근이 κ°€λŠ₯ν•˜λ‹€.

if let <#μƒμˆ˜ 이름#> = <#μ˜΅μ…”λ„ κ°’#> {
   // κ΅¬ν˜„ μ½”λ“œ
   // μ˜΅μ…”λ„ 값을 λ³€μˆ˜μ— λ‹΄λŠ”λ‹€!! λ‹΄κΈ΄λ‹€λ©΄ true, 담기지 λͺ»ν•œλ‹€λ©΄ false
}


let roommateNumbers: Int? = nil
if let roommates = roommateNumbers {
	// roommateNumbers을 roommates에 λ‹΄λŠ”λ‹€.
    
    print (roommates)// 값이 μ—†μ–΄ μ½”λ“œ μ‹€ν–‰ x
}
// 좜λ ₯κ°’ μ—†μŒ

let ticketCounts: Int? = 3
if let ticket = ticketCounts {
	// ticket에 3이 λ‹΄κΈ΄λ‹€. true μƒνƒœμ΄κΈ° λ•Œλ¬Έμ— 좜λ ₯됨
    
    print (ticket)
}
// 좜λ ₯κ°’: 3


// μ˜΅μ…”λ„ 바인딩 ν•  λ³€μˆ˜κ°€ μ—¬λŸ¬ 개인 경우
let boyName : String?
let girlName : String?
// νƒ€μž…λ§Œ μ„ μ–Έ -> μžλ™μœΌλ‘œ nil ν• λ‹Ήλœ μƒνƒœ

// μž¬ν• λ‹Ή ν•΄μ€Œ
boyName = "ν•˜λŠ˜"
girlName = "λ‚˜μ—°"

// , 콀마둜 λ‚˜μ—΄ν•©λ‹ˆλ‹€
if let boy = boyName,
   let girl = girlName {
    print(boy, girl)
}
// 좜λ ₯κ°’: ν•˜λŠ˜ λ‚˜μ—°
// λ‘˜ λ‹€ 값이 μžˆλŠ” μƒνƒœλΌ 좜λ ₯ 성곡

 

 

guard let / guard var: μ„ μ–Έλœ 이후에 λΈ”둝 λ°–μ—μ„œλ„ μ˜΅μ…”λ„μ„ λ²—κΈ°κ³  μ‚¬μš©μ΄ κ°€λŠ₯ν•˜λ„λ‘ ν•œλ‹€. 단, elseλ¬Έκ³Ό return이 ν•„μˆ˜μ΄κΈ° λ•Œλ¬Έμ— μ–Έλž˜ν•‘μ— μ‹€νŒ¨ν•˜κ²Œ 되면 ν•¨μˆ˜λ₯Ό 쑰기에 μ’…λ£Œν•˜κ²Œ λœλ‹€.
{ } λ°–μ—μ„œ μ‚¬μš©μ΄ κ°€λŠ₯ν•˜λ‹€.

let x : Int? = 10
let y : Int? = nil

func opbinding() {
    guard let x = x else { return }
    // 쒌 x : λ§Œλ“€μ–΄μ€€ λ³€μˆ˜/μƒμˆ˜, 우 x : μ„ μ–Έλœ λ³€μˆ˜/μƒμˆ˜
    print(x)

    guard let y = y else { return } // yλŠ” nil μ΄λ―€λ‘œ μ—¬κΈ°μ„œ return 
    print(y) // μœ„μ—μ„œ return ν•˜μ˜€κΈ° λ•Œλ¬Έμ— 이 μ½”λ“œ 라인은 μ‹€ν–‰λ˜μ§€ μ•ŠμŒ
}

opbinding()
// 좜λ ₯κ°’: 10

 

 

β˜‘οΈ μ˜΅μ…”λ„ κ°•μ œ μ–Έλž˜ν•‘

  • κ°•μ œ μ–Έλž˜ν•‘(Force unwrapping)은 !λ₯Ό μ¨μ„œ κ°•μ œλ‘œ μ˜΅μ…”λ„ μΆ”μΆœν•œλ‹€.(λ³€μˆ˜ μ•žμ— !λ₯Ό λΆ™μ΄λŠ” 것은 not의 의미 - ν—·κ°ˆλ¦¬μ§€ 말것!)
  • κ°•μ œ μ–Έλž˜ν•‘μ„ 잘λͺ» μ‚¬μš©ν•  경우 ν”„λ‘œκ·Έλž¨μ΄ λΉ„μ •μƒμ μœΌλ‘œ μ’…λ£Œλ  μˆ˜λ„ μžˆμœΌλ―€λ‘œ λ°˜λ“œμ‹œ nil이 μ•„λ‹Œ 것이 ν™•μ‹€ν•œ μƒν™©μ—μ„œ μ‚¬μš©ν•΄μ•Όν•œλ‹€.(μ΅œλŒ€ν•œ μ•ˆμ“°λŠ”κ²Œ μ’‹μŒ)
  • μ½”λ“œ μ˜ˆμ‹œ
let number = Int("42")!
// String값을 Int둜 λ³€ν™˜ν•˜λŠ” ν•¨μˆ˜λŠ” returnκ°’μœΌλ‘œ μ˜΅μ…”λ„ 값을 λ°˜ν™˜ν•œλ‹€.
print(number)
// 좜λ ₯κ°’: 42

// κ°•μ œ μ–Έλž˜ν•‘μ΄ μ‹€νŒ¨ν•œ 경우
let address: String? = nil
print(address!)
// μ—λŸ¬πŸš¨ λ©”μ‹œμ§€: Unexpectedly found nil while unwrapping an Optional value

 

β˜‘οΈ μ˜΅μ…”λ„ λ³€μˆ˜μ˜ 값이 nil일 λ•Œλ₯Ό μœ„ν•΄ κΈ°λ³Έκ°’ μ„€μ •ν•˜κΈ°

  • 값이 nil일 경우λ₯Ό μœ„ν•΄ 기본값을 μ„€μ •ν•  수 μžˆλ‹€.(nil-coalescing)
    • ?? 을 μ‚¬μš©ν•˜μ—¬ 기본값을 μ‚¬μš©ν•  수 μžˆλŠ”λ°, ?? 이 μ‚¬μš©ν•˜μ—¬ 기본값을 λΆ€μ—¬ν•œ λ³€μˆ˜λŠ” μ˜΅μ…”λ„ νƒ€μž…μ΄ μ•„λ‹ˆλ‹€.
    • let(var) a = b ?? c ν˜•νƒœλ‘œ μ΄λ£¨μ–΄μ§€λŠ”λ° bλŠ” μ˜΅μ…”λ„ νƒ€μž…μ΄κ³ , bκ°€ nil일 κ²½μš°λŠ” a에 cκ°€ λŒ€μž…λ˜κ³ , nil이 아닐 κ²½μš°μ—λŠ” μ˜΅μ…”λ„μ„ μ œκ±°ν•œ 값이 a에 λŒ€μž…λœλ‹€.
var optNumber: Int? = 3
let number = optNumber ?? 5
print(number) // 좜λ ₯κ°’ : 3
//numberλŠ” Int? νƒ€μž…μ΄ μ•„λ‹ˆλΌ Int νƒ€μž…
// μ˜΅μ…”λ„μ„ μ œκ±°ν•˜λ €λŠ” ν–‰μœ„μ΄κΈ° λ•Œλ¬Έμ— Int νƒ€μž…μ΄λ‹€!

optNumber = nil
let number2 = optNumber ?? 5
print(number) // 좜λ ₯κ°’ : 5
//numberλŠ” Int? νƒ€μž…μ΄ μ•„λ‹ˆλΌ Int νƒ€μž…

 

β˜‘οΈ μ˜΅μ…”λ„ 체이닝

  • μ˜΅μ…”λ„μ„ μ—°μ‡„μ μœΌλ‘œ μ‚¬μš©ν•˜λŠ” 것을 μ˜΅μ…”λ„ 체이닝이라고 ν•œλ‹€.
  • .(점) μ„ 톡해 λ‚΄λΆ€ ν”„λ‘œνΌν‹°λ‚˜ λ©”μ„œλ“œμ— μ—°μ†μ μœΌλ‘œ μ ‘κ·Όν•  λ•Œ μ˜΅μ…”λ„ 값이 있으면 μ˜΅μ…”λ„ μ²΄μ΄λ‹μœΌλ‘œ μ ‘κ·Όν•  수 μžˆλ‹€.
  • μ˜ˆμ‹œ μ½”λ“œ
struct Person {
	var name: String
	var address: Address
}

struct Address {
	var city: String
	var street: String
	var detail: String
}

let sam: Person? = Person(name: "Sam", address: Address(city: "μ„œμšΈ", street: "μ‹ λ…Όν˜„λ‘œ", detail: "100"))
print(sam.address.city) // μ—λŸ¬ 🚨. μ—λŸ¬ λ©”μ‹œμ§€: Chain the optional using '?' to access member 'address' only for non-'nil' base values
sam?.address.city  // βœ…
// 좜λ ₯κ°’: μ„œμšΈ
  • λ§Œμ•½ sam이 μ˜΅μ…”λ„μ΄ μ•„λ‹Œ Person νƒ€μž…μ΄μ—ˆλ‹€λ©΄ sam.address.city κ°€ κ°€λŠ₯ν•˜λ‹€. ν•˜μ§€λ§Œ sam이 μ˜΅μ…”λ„ νƒ€μž…μ΄κΈ° λ•Œλ¬Έμ— address에 μ ‘κ·Όν•˜λ €λ©΄ sam?.address.city ν˜•νƒœλ‘œ 이루어져야 ν•œλ‹€.
  • μœ„ μ½”λ“œ 쀑 “sam?.address.city” 을 λ‹€μ‹œ μ‚΄νŽ΄λ³΄λ©΄, sam == nil 일 경우 μ—λŸ¬κ°€ λ‚˜μ§€ μ•Šκ³  λ’€ μ½”λ“œκ°€ μ‹€ν–‰λ˜μ§€ μ•ŠλŠ”λ‹€.
    λ‹€λ₯Έ μ–Έμ–΄μ˜ null은 .으둜 μ°Έμ‘°λ₯Ό ν•˜λ©΄ λ°”λ‘œ NullPointerException μ—λŸ¬κ°€ λ°œμƒν•œλ‹€.
    λ”°λΌμ„œ Swiftμ—μ„œμ˜ nil은 λ©”λͺ¨λ¦¬μ˜ μ£Όμ†Œκ°’μ΄ μ—†μŒμ„ λ‚˜νƒ€λ‚΄λŠ” null이 μ•„λ‹ˆλΌ 값이 μ—†μŒμ„ λ‚˜νƒ€λ‚΄λŠ” κ°’!! (λ©”λͺ¨λ¦¬μ— μ˜¬λΌκ°„ μƒνƒœμž„, μ‹€μ œλ‘œλŠ” λ’€μ—μ„œ 배울 Enum)이닀.