[Swift5] Optional Chaining 2

16877 단어 swiftswift
  • 다음은 Swift 5.6 Doc의 Optional Chaining 공부 내용을 정리했음을 밝힙니다.

Optional Chaining 2

옵셔널 체이닝으로 메소드 호출

옵셔널 값에 메소드를 사용하거나, 메소드 호출이 성공적인지 확인하는 용도로 옵셔널 체이닝을 사용할 수 있다. 이 메소드가 리턴 값이 없어도 사용 가능하다.

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

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."

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."

johnresidence 메소드 printNumberOfRooms는 리턴 타입이 없다. 리턴 타입이 없는 함수 및 메소드는 빈 튜플 ()을 리턴한다.

옵셔널 체이닝과 함께 옵셔널 값 상에 이런 (리턴 타입이 빈 튜플인) 메소드를 사용한다면 Void가 아니라 Void?를 리턴한다는 데 주의하자. 옵셔널 바인딩을 통해 (널 값을 확인해) 메소드를 사용할 수 있는지 체크하자.

프로퍼티 값을 옵셔널 체이닝을 통해 설정할 때에도 nil을 리턴한다면 값 설정이 불가능하다는 것을 알 수 있다. 함수 및 메소드 호출 여부 / 프로퍼티 접근 여부 등을 옵셔널 체이닝을 통해 체크할 수 있다는 게 주요 관건.

옵셔널 체이닝으로 서브스크립트 접근

옵셔널 체이닝을 통해 옵셔널 값의 서브스크립트로 값을 설정하거나 확인할 수 있다. (메소드 호출처럼) 서브스크립트 호출이 성공했는지도 확인할 수 있다.

서브스크립트를 옵셔널 값에 옵셔널 체이닝을 통해 사용하려면 ?을 서브스크립트 괄호 뒤에 붙인다.

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."

john.residence?[0] = Room(name: "Bathroom")

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."

john 인스턴스의 residence가 널 값이기 때문에 서브스크립트 조회가 실패한다. residencejohnsHouse를 할당하면 더 이상 널 값이 아니기 때문에 값을 조회할 수 있다.

옵셔널 타입 서브스크립트 접근

서브스크립트가 옵셔널 타입을 리턴하면 옵셔널 리턴 값에 체인하기 위해 서브스크립트 괄호 다음에 ?를 붙이자.

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 딕셔너리는 카-값 쌍의 딕셔너리로 문자열 키를 통해 숫자 배열에 접근할 수 있다. 특정 키가 널 값의 값을 가지고 있을 수도 (즉 testScores에 키가 없을 수도) 있음을 []?을 통해 알 수 있다. testScores["Brian"]?은 키 자체가 없기 때문에 널 값이 리턴되고, 값을 할당할 수 없다.

체이닝 멀티 레벨을 링크하기

모델 구조 깊이 있는 프로퍼티, 메소드, 서브스크립트에 멀티 레벨의 옵셔널 체이닝할 수 있다. 멀티 레벨 옵셔널 체이닝은 리턴 값에 멀티 레벨 옵셔널리티를 주지는 않는다. 옵셔널 체이닝으로 Int 값을 받을 때에는 Int? 옵셔널이 리턴되고, Int? 값을 받을 때에도 Int?가 리턴된다.

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."

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."

johnStreet는 멀티 레벨 옵셔널 체이닝을 통해 값(프로퍼티, 인스턴스 등)을 확인하고 있다.

옵셔널 리턴 값으로 메소드 체이닝

옵셔널 체이닝을 통해 옵셔널 타입 값을 리턴하는 메소드를 호출하고 이 메소드가 리턴하는 값에 체이닝할 수 있다.

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 doesn't begin with \"The\".")
    }
}
// Prints "John's building identifier begins with "The"."

buildingIdentifier()?는 메소드 괄호 다음에 ?를 체이닝했다는 것을 보여준다. 이때 괄호 다음에 ?를 붙여 체이닝하는 것은 메소드 자체가 아니라 메소드가 리턴하는 옵셔널 값에 체이닝해야 하기 때문이다.

좋은 웹페이지 즐겨찾기