Potato
μ•ˆλ…•ν•˜μ„Έμš”, κ°μž‘λ‹ˆλ‹€?πŸ₯” ^___^ 😺 github λ°”λ‘œκ°€κΈ° πŸ‘‰πŸ»

Swift/Swift Documents

[Swift] 곡식 λ¬Έμ„œ 정리 (16) - Optional Chaining (μ˜΅μ…”λ„ 체이닝, ?)

감자 πŸ₯” 2022. 3. 8. 12:08
λ°˜μ‘ν˜•

μ•ˆλ…•ν•˜μ„Έμš”, κ°μžμž…λ‹ˆλ‹€. μ˜€λžœλ§Œμ— λŒμ•„μ˜¨ 것 κ°™μ€λ°μš”, (μ•„λ‹Œκ°€ γ…Ž) μš”μ¦˜ μŠ€ν„°λ””λ§Œ μ§„ν–‰ν•˜κ³  μŠ€ν„°λ””ν•œ λ‚΄μš©μ„ μ—…λ‘œλ“œν•˜λŠ” 것을 κΉŒλ¨Ήμ—ˆλ„€μš”. 그리고 μ‚¬λžŒμ΄λΌλŠ”κ²Œ,, 쑰금 μš”μ¦˜ λ‚˜νƒœν•΄μ Έμ„œ γ… γ…  λ‹€μ‹œ ν•œλ²ˆ ν™”μ΄νŒ… μ™ΈμΉ˜κ³  갓생살기 λ‹€μ‹œ μ‹œμž‘ν•©λ‹ˆλ‹€ ν—ˆν—› 

Swift Document chap16. optional chaining λ³΄λŸ¬κ°€κΈ°

 

Optional Chaining — The Swift Programming Language (Swift 5.6)

Optional Chaining Optional chaining is a process for querying and calling properties, methods, and subscripts on an optional that might currently be nil. If the optional contains a value, the property, method, or subscript call succeeds; if the optional is

docs.swift.org

 


 

Optional Chanining (μ˜΅μ…”λ„ 체이닝)

μ˜΅μ…”λ„ 체이닝은 nil일 수 도 μžˆλŠ” ν”„λ‘œνΌν‹°λ‚˜, λ©”μ†Œλ“œ 그리고 μ„œλΈŒμŠ€ν¬λ¦½νŠΈμ— Query(질문)λ₯Ό ν•˜λŠ” 과정을 λ§ν•œλ‹€.

λ§Œμ•½ μ˜΅μ…”λ„μ΄ ν”„λ‘œνΌν‹°λ‚˜ λ©”μ†Œλ“œ ν˜Ήμ€ μ„œλΈŒμŠ€ν¬λ¦½νŠΈμ— λŒ€ν•œ 값을 κ°–κ³  μžˆλ‹€λ©΄ κ·Έ 값을 λ°˜ν™˜ν•˜κ³  λ§Œμ•½ 값이 nil 이라면 nil을 λ°˜ν™˜ν•œλ‹€. μ—¬λŸ¬ 개의 쿼리λ₯Ό ν™•μΈν•˜λ©΄ μ•Œ 수 μžˆλŠ”λ° μ—°κ²°λœ 체인쀑 ν•˜λ‚˜λΌλ„ 결과값이 nil이라면 전체 체인의 κ²°κ³ΌλŠ” nil이 λ°˜ν™˜λœλ‹€.

 

κ°•μ œ μ–Έλž˜ν•‘μ˜ λŒ€μ²΄λ‘œμ¨μ˜ μ˜΅μ…”λ„ 체이닝

μ˜΅μ…”λ„ 체이닝은 μ˜΅μ…”λ„ κ°’ 뒀에 λ¬ΌμŒν‘œ(?)λ₯Ό λΆ™μ—¬μ„œ ν‘œν˜„ κ°€λŠ₯ν•˜λ‹€. μ˜΅μ…”λ„μ„ μ‚¬μš©ν•  수 μžˆλŠ” κ°’μ—λŠ” ν”„λ‘œνΌν‹°, λ©”μ„œλ“œ, 그리고 μ„œλΈŒμŠ€ν¬λ¦½νŠΈκ°€ ν¬ν•¨λœλ‹€. μ˜΅μ…”λ„ 값을 κ°•μ œ μ–Έλž˜ν•‘ ν•˜κΈ° μœ„ν•΄μ„œ 뒀에 λŠλ‚Œν‘œ(!)λ₯Ό λΆ™μ΄λŠ” 것과 문법이 λΉ„μŠ·ν•œλ°, κ°€μž₯ 큰 μ°¨μ΄λŠ” κ°•μ œ μ–Έλž˜ν•‘μ„ ν–ˆλŠ”λ° λ§Œμ•½ κ·Έ 값이 μ—†μœΌλ©΄ λŸ°νƒ€μž„ μ—λŸ¬κ°€ λ°œμƒν•˜μ§€λ§Œ, μ˜΅μ…”λ„ 체이닝을 μ‚¬μš©ν•˜λ©΄ λŸ°νƒ€μž„ μ—λŸ¬ λŒ€μ‹  nil μ΄ λ°˜ν™˜λœλ‹€λŠ” 것이닀.

μ˜΅μ…”λ„ 체이닝에 μ˜ν•΄ nil 값이 호좜 될 수 있기 λ•Œλ¬Έμ— μ˜΅μ…”λ„ μ²΄μ΄λ‹μ˜ λ°˜ν™˜κ°’μ€ 항상 μ˜΅μ…”λ„ 값이 λœλ‹€. (Intλ₯Ό λ°˜ν™˜ν•˜λŠ” λ©”μ„œλ“œμΈ 경우, μ˜΅μ…”λ„ 체이닝이 μ„±κ³΅μ μœΌλ‘œ μ‹€ν–‰λ˜λ©΄ Int?κ°€ λ°˜ν™˜)

λ‹€μŒ μ½”λ“œλŠ” μ˜΅μ…”λ„ 체이닝이 κ°•μ œ μ–Έλž˜ν•‘κ³Ό μ–΄λ–»κ²Œ λ‹€λ₯Έμ§€ λ³΄μ—¬μ£ΌλŠ” μ˜ˆμ œμ΄λ‹€.

class Person {
    var residence: Residence?
}

class Residence {
    var numberOfRooms = 1
}

Residence μΈμŠ€ν„΄μŠ€λŠ” numberOfRoomsμ΄λΌλŠ” Intν”„λ‘œνΌν‹°λ₯Ό ν•˜λ‚˜ μ†Œμœ ν•˜κ³  있고, Person μΈμŠ€ν„΄μŠ€λŠ” μ˜΅μ…”λ„ residence ν”„λ‘œνΌν‹°λ₯Ό Residence? λ‘œ μ†Œμœ ν•œλ‹€. λ§Œμ•½ Person μ΄λΌλŠ” μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜λ©΄ residence ν”„λ‘œνΌν‹°λŠ” μ˜΅μ…”λ„μ˜ κΈ°λ³Έ 값인 nil λ‘œ μ΄ˆκΈ°ν™” λœλ‹€.

let john = Person()

즉, 이 μ½”λ“œμ—μ„œ john은 residence ν”„λ‘œνΌν‹°κ°€ nil μΈ 값을 μ†Œμœ ν•˜κ²Œ λœλ‹€.

let roomCount = john.residence!.numberOfRooms
//ERROR!!!!

λ§Œμ•½ 이 Person의 residence에 numberOfRooms ν”„λ‘œνΌν‹°μ— μ ‘κ·Όν•˜κΈ° μœ„ν•΄ λŠλ‚Œν‘œλ₯Ό μ΄μš©ν•΄ κ°•μ œ μ–Έλž˜ν•‘μ„ μ‹œλ„ν•œλ‹€λ©΄, residence κ°€ μ–Έλž˜ν•‘ν•  값이 μ—†κΈ° λ•Œλ¬Έμ— λŸ°νƒ€μž„ μ—λŸ¬κ°€ λ°œμƒν•œλ‹€.

numberOfRooms μ˜ 값에 μ ‘κ·Όν•˜κΈ° μœ„ν•΄ κ°•μ œ μ–Έλž˜ν•‘ λŒ€μ‹  μ˜΅μ…”λ„ 체이닝을 μ‚¬μš©ν•  수 μžˆλ‹€. μ˜΅μ…”λ„ 체이닝을 μ‚¬μš©ν•˜κΈ° μœ„ν•΄ λŠλ‚Œν‘œ! λŒ€μ‹  λ¬ΌμŒν‘œ?λ₯Ό μ‚¬μš©ν•œλ‹€.

if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \\(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}
// Prints "Unable to retrieve the number of rooms."

μ˜΅μ…”λ„ μ²΄μ΄λ‹μ΄λΌλŠ” 단어 처럼 residence ν”„λ‘œνΌν‹°λ“€μ€ μ„œλ‘œ λ¬Άμ—¬μžˆλ‹€. κ·Έλž˜μ„œ μœ„ μ½”λ“œμ—μ„œ numberOfRoomsν”„λ‘œνΌν‹°λŠ” μ˜΅μ…”λ„μ΄ μ•„λ‹ˆμ§€λ§Œ 이 값에 μ ‘κ·Όν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν–ˆλ˜ μΈμŠ€ν„΄μŠ€μ˜ ν”„λ‘œνΌν‹° residence κ°€ μ˜΅μ…”λ„μ΄κΈ° λ•Œλ¬Έμ— μ΅œμ’… 값은 μ˜΅μ…”λ„μ΄ λœλ‹€.

john.residence = Residence()

if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \\(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}
// Prints "John's residence has 1 room(s)."

nil μ΄μ—ˆλ˜ residence값에 ResidenceμΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•΄μ„œ μΆ”κ°€ν•  수 μžˆλ‹€.

john.residence λŠ” 이제 nil 이 μ•„λ‹ˆλΌ Residence() μΈμŠ€ν„΄μŠ€λ₯Ό κ°–λŠ”λ‹€. κ·Έλž˜μ„œ μ˜΅μ…”λ„ μ²΄μ΄λ‹μœΌλ‘œ numberOfRooms값에 μ ‘κ·Ό ν–ˆμ„ λ•Œ 1을 λ¦¬ν„΄ν•œλ‹€.

 


 

μ˜΅μ…”λ„ 체이닝을 μœ„ν•œ λͺ¨λΈ 클래슀 μ •μ˜

μ˜΅μ…”λ„ 체이닝을 ν”„λ‘œνΌν‹°, λ©”μ„œλ“œ, 그리고 μ„œλΈŒμŠ€ν¬λ¦½νŠΈμ—μ„œ μ‚¬μš©ν•  수 μžˆλŠ”λ°, ν•œ 단계가 μ•„λ‹Œ μ—¬λŸ¬ λ‹¨κ³„λ‘œ μ‚¬μš©ν•  수 μžˆλ‹€. 쑰금 더 λ³΅μž‘ν•œ μ½”λ“œ 예제둜 μ‚΄νŽ΄λ³΄μž.

class Person {
    var residence: Residence?
}

class Residence {
    var rooms = [Room]()
    var numberOfRooms: Int {
        return rooms.count
    }
    subscript(i: Int) -> Room {
        get {
            return rooms[i]
        }
        set {
            rooms[i] = newValue
        }
    }
    func printNumberOfRooms() {
        print("The number of rooms is \\(numberOfRooms)")
    }
    var address: Address?
}

class Room {
    let name: String
    init(name: String) { self.name = name }
}

class Address {
    var buildingName: String?
    var buildingNumber: String?
    var street: String?
    func buildingIdentifier() -> String? {
        if let buildingNumber = buildingNumber, let street = street {
            return "\\(buildingNumber) \\(street)"
        } else if buildingName != nil {
            return buildingName
        } else {
            return nil
        }
    }
}

μœ„ μ½”λ“œλŠ” Person, Residence λͺ¨λΈμ„ ν™•μž₯ν•˜μ—¬ Roomκ³Ό Address ν΄λž˜μŠ€λ₯Ό μΆ”κ°€ν•œ λͺ¨λΈμ„ μ •μ˜ν•œλ‹€.

  • Person ν΄λž˜μŠ€λŠ” μœ„μ™€ 동일
  • Residence
    • roomsλΌλŠ” ν”„λ‘œνΌν‹°λ₯Ό μ†Œμœ ν•œλ‹€. [Room] νƒ€μž…μ˜ 빈 λ°°μ—΄λ‘œ μ΄ˆκΈ°ν™” λœλ‹€. 이전 λ²„μ „μ˜ Residenceκ°€ Room μΈμŠ€ν„΄μŠ€μ˜ 배열을 μ†Œμœ ν•˜κ³  있기 λ•Œλ¬Έμ— numberOfRooms ν”„λ‘œνΌν‹°λŠ” 계산 ν”„λ‘œνΌν‹°λ‘œ μ„ μ–Έλœλ‹€. rooms λ°°μ—΄μ„ μ ‘κ·Όν•˜κΈ° μœ„ν•œ λ‹¨μΆ•μ–΄λ‘œ μ„œλΈŒμŠ€ν¬λ¦½νŠΈλ₯Ό μ„ μ–Έν–ˆμŒ.
  • Room
    • rooms λ°°μ—΄μ˜ Roomν΄λž˜μŠ€λŠ”, 이름 ν•˜λ‚˜λ₯Ό μ΄ˆκΈ°ν™” λ•Œ 인자둜 λ°›λŠ” κ°„λ‹¨ν•œ 클래슀
  • Address
    • 이 ν΄λž˜μŠ€λŠ” 3개의 String? μ˜΅μ…”널 ν”„λ‘œνΌν‹°λ₯Ό κ°–λŠ”λ‹€. 처음 λ‘κ°œλŠ” buildingName, buildingNumber μ΄κ³  λΉŒλ”© μ£Όμ†Œλ₯Ό κ΅¬λΆ„ν•œλ‹€. λ§ˆμ§€λ§‰ street ν”„λ‘œνΌν‹°λŠ” 거리의 μ£Όμ†Œλ₯Ό λ‚˜νƒ€λ‚Έλ‹€.
    • buildingIdentifier() λΌλŠ” String? νƒ€μž…μ˜ λ©”μ„œλ“œλ₯Ό μ§€μ›ν•œλ‹€. 이 λ©”μ„œλ“œλŠ” buildingNumber와 street을 확인해 값이 있으면 buildingNumber와 κ²°ν•©λœ street κ°’을 λ³€ν™˜ν•˜κ³  μ—†μœΌλ©΄ nil을 λ°˜ν™˜ν•œλ‹€.

 

μ˜΅μ…”λ„ 체이닝을 ν†΅ν•œ ν”„λ‘œνΌν‹°μ— μ ‘κ·Ό

μ˜΅μ…”λ„ 체이닝을 μ΄μš©ν•΄μ„œ ν”„λ‘œνΌν‹°μ— μ ‘κ·Όν•  수 μžˆλ‹€.

let john = Person()
if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \\(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}
// Prints "Unable to retrieve the number of rooms."

let someAddress = Address()
someAddress.buildingNumber = "29"
someAddress.street = "Acacia Road"
john.residence?.address = someAddress

μœ„ μ½”λ“œμ—μ„œ, residence?κ°€ nil 이기 λ•Œλ¬Έμ— μ˜΅μ…”λ„ 체이닝 κ²°κ³Ό nil을 ν˜ΈμΆœν•˜κ²Œ λœλ‹€.

μ˜΅μ…”λ„ 체이닝은 값을 ν• λ‹Ήν• λ•Œλ„ μ‚¬μš© κ°€λŠ₯ν•˜λ‹€. Address() μΈμŠ€ν„΄μŠ€λ₯Ό 생성해 john.residence의 address둜 ν• λ‹Ήν•˜λŠ” μ½”λ“œμ΄λ‹€. john.residence?κ°€ nil이기 λ•Œλ¬Έμ— address ν• λ‹Ήμ€ μ‹€νŒ¨ν•˜κ²Œ λœλ‹€. 할당도 ν• λ‹Ήλ°›λŠ” μ™Όμͺ½ 항이 nil이면 μ•„μ˜ˆ 였λ₯Έμͺ½ 항이 μ‹€ν–‰λ˜μ§€ μ•ŠλŠ”λ‹€.

func createAddress() -> Address {
    print("Function was called.")
  let someAddress = Address()
    someAddress.buildingNumber = "29"
    someAddress.street = "Acacia Road"    

    return someAddress
}
john.residence?.address = createAddress() //λ°˜μ‘ μ—†μŒ 

μ§„μ§œλ‘œ μ™Όμͺ½ν•­μ΄ nil이면 였λ₯Έμͺ½ν•­μ΄ μ•„μ˜ˆ μ‹€ν–‰λ˜μ§€ μ•ŠλŠ”μ§€ μ•Œμ•„λ³΄κΈ° μœ„ν•΄ createAddressλ©”μ„œλ“œλ₯Ό λ§Œλ“€μ—ˆλ‹€. john.residence?.address = createAddress() μ—μ„œ ν˜ΈμΆœν•˜λ©΄ “Function was called” κ°€ 좜λ ₯λ˜μ§€ μ•ŠλŠ”λ‹€. μ΄ λ©”μ„œλ“œκ°€ μ‹€ν–‰λ˜μ§€ μ•Šμ•˜μŒμ„ μ˜λ―Έν•œλ‹€.


 

μ˜΅μ…”λ„ 체이닝을 ν†΅ν•œ λ©”μ„œλ“œ 호좜

μ˜΅μ…”λ„ 체이닝을 μ΄μš©ν•˜μ—¬ λ©”μ„œλ“œλ₯Ό 호좜 ν•  수 μžˆλ‹€.

func printNumberOfRooms() {
    print("The number of rooms is \\(numberOfRooms)")
}

μœ„ λ©”μ„œλ“œλŠ” 리턴값이 λͺ…μ‹œλ˜μ§€ μ•ŠλŠ”λ‹€. ν•˜μ§€λ§Œ ν•¨μˆ˜λ‚˜ λ©”μ„œλ“œλŠ” 리턴값이 μ—†λŠ” 경우 μ•”μ‹œμ μœΌλ‘œ VoidλΌλŠ” 값을 κ°–λŠ”λ‹€. κ·Έλž˜μ„œ 이 λ©”μ„œλ“œκ°€ μ˜΅μ…”λ„ μ²΄μ΄λ‹μ—μ„œ 호좜되면 λ°˜ν™˜κ°’μ€ Voidκ°€ μ•„λ‹ˆλΌ Void? κ°€ λœλ‹€.

if john.residence?.printNumberOfRooms() != nil {
    print("It was possible to print the number of rooms.")
} else {
    print("It was not possible to print the number of rooms.")
}
// Prints "It was not possible to print the number of rooms."

μœ„ μ½”λ“œλŠ” john.residence?.printNumberOfRooms() λ©”μ†Œλ“œ 호좜의 κ²°κ³Όκ°€ nil인지 μ•„λ‹Œμ§€ 비ꡐλ₯Ό ν•˜κ³  κ·Έ 결과에 λŒ€ν•œ 처리λ₯Ό ν•œλ‹€. μœ„μ—μ„œ μ–ΈκΈ‰ν–ˆλ˜ κ²ƒμ²˜λŸΌ printNumberofRooms()λŠ” Void?κ°€ λ°˜ν™˜λ˜μ„œ nil 비ꡐλ₯Ό ν•  수 μžˆλ‹€.

μ˜΅μ…”λ„ 체이닝을 톡해 값을 ν• λ‹Ήν•˜λ©΄ 값을 Void?둜 λ°˜ν™˜ν•œλ‹€. κ·Έλž˜μ„œ 이 값이 nil 인지 μ•„λ‹Œμ§€ 비ꡐ할 수 μžˆλ‹€.

if (john.residence?.address = someAddress) != nil {
    print("It was possible to set the address.")
} else {
    print("It was not possible to set the address.")
}
// Prints "It was not possible to set the address."

 


 

μ˜΅μ…”λ„ 체이닝을 ν†΅ν•œ μ„œλΈŒ 슀크립트 μ ‘κ·Ό

μ˜΅μ…”λ„ 체이닝을 ν™œμš©ν•˜μ—¬ μ˜΅μ…”λ„ 값을 μ„œλΈŒμŠ€ν¬λ¦½νŠΈλ‘œ μ ‘κ·Όν•  수 μžˆλ‹€. [] μ „에 ? λ₯Ό 적어 ?[]둜 μ‚¬μš©ν•œλ‹€.

if let firstRoomName = john.residence?[0].name {
    print("The first room name is \\(firstRoomName).")
} else {
    print("Unable to retrieve the first room name.")
}
// Prints "Unable to retrieve the first room name."

μœ„ μ½”λ“œλŠ” μ„œλΈŒμŠ€ν¬λ¦½νŠΈλ₯Ό μ΄μš©ν•΄ rooms μ—μ„œ 첫  rooms μ˜ name을 μš”μ²­ν•˜λŠ” μ½”λ“œμ΄λ‹€. ν˜„μž¬ john.residence κ°€ nil 이기 λ•Œλ¬Έμ— μ„œλΈŒμŠ€ν¬λ¦½νŠΈ 접근은 μ‹€νŒ¨ν•˜κ²Œ λœλ‹€.

  • μΆ”κ°€μ„€λͺ…
  • μ˜΅μ…”λ„ μ²΄μ΄λ‹μ—μ„œ μ„œλΈŒμŠ€ν¬λ¦½νŠΈλ‘œ 값을 κ°€μ Έμ˜€λŠ” 것과 μœ μ‚¬ν•œ ν˜•νƒœλ‘œ 값을 ν• λ‹Ήν•  수 μžˆλ‹€. john.residence?[0] = Room (name: “Bathroom”) μ΄ μ½”λ“œλŠ” 첫 room 값을 ν• λ‹Ήν•˜λŠ” μ½”λ“œμΈλ° rooms을 ν• λ‹Ήν•˜μ§€ λͺ»ν•˜κ³  fail이 λ°œμƒν•œλ‹€. κ·Έ μ΄μœ λŠ” residence κ°€ ν˜„μž¬ nil 이기 λ•Œλ¬Έμ΄λ‹€.
let johnsHouse = Residence()
johnsHouse.rooms.append(Room(name: "Living Room"))
johnsHouse.rooms.append(Room(name: "Kitchen"))
john.residence = johnsHouse

 if let firstRoomName = john.residence?[0].name {
    print("The first room name is \\(firstRoomName).")
} else {
    print("Unable to retrieve the first room name.")
}
// Prints "The first room name is Living Room."

μœ„ μ½”λ“œμ™€ 같이 Residence μΈμŠ€ν„΄μŠ€λ₯Ό ν• λ‹Ήν•˜λ©΄ residence μ„œλΈŒμŠ€ν¬λ¦½νŠΈλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

 

μ˜΅μ…”λ„ νƒ€μž…μ˜ μ„œλΈŒμŠ€ν¬λ¦½νŠΈ μ ‘κ·Ό

λ§Œμ•½ swift의 Dictionary νƒ€μž…μ΄ μ„œλΈŒμŠ€ν¬λ¦½νŠΈμ˜ 결과둜 μ˜΅μ…”λ„ 값을 λ°˜ν™˜ν•œλ‹€κ³  ν•˜λ©΄, κ·Έ 뒀에 λ¬ΌμŒν‘œ?λ₯Ό λΆ™μ—¬ μ€€λ‹€. Dictionary νƒ€μž…μ€ key-value 둜 λ™μž‘ν•˜κΈ° λ•Œλ¬Έμ— 항상 κ·Έ 사전에 keyκ°€ μ‘΄μž¬ν•œλ‹€λŠ 보μž₯이 μ—†κΈ° λ•Œλ¬Έμ— μ˜΅μ…”λ„ 값을 λ°˜ν™˜ν•œλ‹€.

var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]]
testScores["Dave"]?[0] = 91
testScores["Bev"]?[0] += 1
testScores["Brian"]?[0] = 72
// the "Dave" array is now [91, 82, 84] and the "Bev" array is now [80, 94, 81]

μœ„ μ½”λ“œλŠ” testScores λΌλŠ” Dictionaryμ—μ„œ νŠΉμ • key에 λŒ€ν•œ 값을 get ν˜Ήμ€ set ν•˜λŠ” μ½”λ“œμ΄λ‹€. Dave, Bev와 κ΄€λ ¨ν•œ 값은 μ²˜λ¦¬κ°€ 되고, Brain은 λ“±λ‘λœ key κ°€ μ—†κΈ° λ•Œλ¬Έμ— κ΄€λ ¨ν•œ 아무일도 μΌμ–΄λ‚˜μ§€ μ•ŠλŠ”λ‹€.


 

μ²΄μ΄λ‹μ˜ 닀쀑 μ—°κ²°

μ˜΅μ…”λ„ 체이닝이 μ—¬λŸ¬ 단계에 걸쳐 μ—°κ²° 될 수 μžˆλ‹€. μƒμœ„ 값이 μ˜΅μ…”λ„ 값인 경우 ν•˜μœ„λ„ μ˜΅μ…”λ„ 값이라고 ν•΄μ„œ 더 μ˜΅μ…”λ„ 해지진 μ•ŠλŠ”λ‹€. μ˜΅μ…”λ„μ€ μ˜΅μ…”λ„μ΄λ‹€.

  • μ˜΅μ…”λ„ μ²΄μ΄λ‹μ˜ μƒμœ„ 레벨 값이 μ˜΅μ…”λ„μΈ 경우 ν˜„μž¬ 값이 μ˜΅μ…”λ„μ΄ μ•„λ‹ˆλ”λΌλ„ κ·Έ 값은 μ˜΅μ…”λ„κ°’μ΄ λœλ‹€.
  • μ˜΅μ…”λ„ μ²΄μ΄λ‹μ˜ μƒμœ„ 레벨 값이 μ˜΅μ…”λ„μ΄κ³  ν˜„μž¬ 값이 μ˜΅μ…”λ„ 이라고 ν•΄μ„œ 더 μ˜΅μ…”λ„ν•˜κ²Œ λ˜μ§„ μ•ŠλŠ”λ‹€.
  • μ˜΅μ…”λ„ 체이닝을 톡해 값을 κ²€μƒ‰ν•˜κ±°λ‚˜ λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ λͺ‡ 단계λ₯Ό κ±°μΉ˜λŠ”μ§€ 상관없이 μ˜΅μ…”λ„μ„ λ°˜ν™˜ν•œλ‹€.

예제λ₯Ό μ‚΄νŽ΄λ³΄μž.

if let johnsStreet = john.residence?.address?.street {
    print("John's street name is \\(johnsStreet).")
} else {
    print("Unable to retrieve the address.")
}
// Prints "Unable to retrieve the address."

john.residenceλŠ” validν•œ Residence μΈμŠ€ν„΄μŠ€λ₯Ό κ°–κ³  μžˆμ§€λ§Œ addressκ°€ nilμ΄μ–΄μ„œ 이 μ˜΅μ…”λ„ 체이닝은 fail이 λœλ‹€. 비둝 μƒμœ„μ˜ μ˜΅μ…”λ„ 값인 john.residenceκ°€ true여도 ν•˜μœ„ 값이 nil 이면 체이닝은 fail이 λœλ‹€.

let johnsAddress = Address()
johnsAddress.buildingName = "The Larches"
johnsAddress.street = "Laurel Street"
john.residence?.address = johnsAddress

if let johnsStreet = john.residence?.address?.street {
    print("John's street name is \\(johnsStreet).")
} else {
    print("Unable to retrieve the address.")
}
// Prints "John's street name is Laurel Street."

μœ„ μ½”λ“œλŠ” Address μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±μ—μ„œ ν• λ‹Ήν•˜κ³  λ‹€μ‹œ μ˜΅μ…”λ„ 체이닝을 ν•΄λ³Έ μ½”λ“œμ΄λ‹€. Residence μΈμŠ€ν„΄μŠ€μ˜ Address μΈμŠ€ν„΄μŠ€κ°€ λͺ¨λ‘ μ‘΄μž¬ν•˜κΈ° λ•Œλ¬Έμ— μ˜΅μ…”λ„ 체이닝은 sucess κ°€ λœλ‹€.


 

μ²΄μ΄λ‹μ—μ„œ μ˜΅μ…”λ„ 값을 λ°˜ν™˜ν•˜λŠ” λ©”μ„œλ“œ

μ•„λž˜ μ½”λ“œλŠ” μ˜΅μ…”λ„ μ²΄μ΄λ‹μ—μ„œ λ°˜ν™˜ 값이 μžˆλŠ” λ©”μ„œλ“œλ₯Ό 호좜 ν•˜λŠ” μ½”λ“œμ΄λ‹€.

if let buildingIdentifier = john.residence?.address?.buildingIdentifier() {
    print("John's building identifier is \\(buildingIdentifier).")
}
// Prints "John's building identifier is The Larches."

λ§Œμ•½ λ©”μ†Œλ“œμ˜ λ°˜ν™˜ 값을 κ°–κ³  좔가적인 행동을 더 ν•˜κ³  μ‹Άλ‹€λ©΄ λ©”μ†Œλ“œ 호좜 ν‘œν˜„ 뒀에 λ¬ΌμŒν‘œ(?)λ₯Ό 뢙이고 κ·Έ 행동을 적어주면 λœλ‹€. μ•žμ—μ„œ μ–ΈκΈ‰ ν–ˆλ˜ 것 처럼 μ˜΅μ…”λ„ 체이닝에 λ¬Όλ € 있기 λ•Œλ¬Έμ— λ©”μ†Œλ“œμ˜ λ°˜ν™˜ 값도 μ˜΅μ…”λ„μ΄ λΌμ„œ κ·Έ ν‘œμ‹œλ₯Ό ν•΄μ€˜μ•Ό ν•œλ‹€.

if let beginsWithThe =
    john.residence?.address?.buildingIdentifier()?.hasPrefix("The") {
    if beginsWithThe {
        print("John's building identifier begins with \\"The\\".")
    } else {
        print("John's building identifier does not begin with \\"The\\".")
}
}
// Prints "John's building identifier begins with "The"."

μ˜΅μ…”λ„μ΄ λ°˜ν™˜ 값에 걸렀있고, λ©”μ„œλ“œ μžμ²΄μ— κ±Έλ €μžˆλŠ” 것이 μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— λ©”μ„œλ“œ κ΄„ν˜Έ 뒀에 ? λ₯Ό λΆ™μ—¬μ€˜μ•Ό ν•œλ‹€.

λ°˜μ‘ν˜•