Mobile/ios & swift

[Swift 4] Optional Chaining(4) - 옵셔널 체이닝을 이용하여 서브스크립트 접근하기

버리야 2018. 3. 20. 01:02
반응형


이 포스팅은 The Swift Programming Language (Swift 4.1) 의 Optional Chaining 문서를 보고 이해하며 제 것으로 만들면서 정리해 놓은 문서입니다.



원문 

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html#//apple_ref/doc/uid/TP40014097-CH21-ID245




옵셔널 체이닝을 이용하여 서브스크립트 접근하기(Accessing Subscripts Through Optional Chaining)


옵셔널 값의 서브스크립트로부터 값을 가져오거나 설정하기 위해, 옵셔널 체이닝을 사용 할 수 있고, 서브스크립트 호출이 성공하는지 확인한다.

예제는 Residence클래스에서 정의된 서브스크립트를 사용하는john.residence프로퍼티의 rooms배열에서 첫번째 방의 이름을 가져오려 시도한다.

john.residence는 현재 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는 옵셔널 값이기 때문에, 서브스크립트 호출에서 옵셔널 체이닝 물음표(?) 표시는 john.residence바로 뒤에 위치하며, 서브스크립트 대괄호([]) 앞에 표시한다.

비슷하게, 옵셔널 체이닝으로 서브스크립트에 새로운 값을 설정 할 수 있습니다.

 

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


실제 Residence인스턴스를 john.residence로 생성하고 할당하면, rooms배열에는 하나 이상의 Room인스턴스가 있으며, 옵셔널 체이닝을 사용하여 rooms배열에 있는 실제 항목을 접근하기 위해, Residence서브스크립트를 사용할 수 있다.


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


옵셔널 타입의 서브스크립트 접근하기(Accessing Subscripts of Optional Type)

서브스크립트가 옵셔널 타입의 값을 반환하면 -Swift의 Dictionary타입의 서브스크립트 키 처럼- 옵셔널 반환 값을 연결(chain)하기 위해, 물음표(?)는 서브스크립트의 닫힌 대괄호(]) 뒤에 표시한다.

 

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를 정의한다.

이 dictionary에는 String 키를 Int 값의 배열에 매핑하는 두 개의 키 - 값 쌍이 들어 있다. 이 예제에서는 옵셔널 체인을 사용하여 "Dave"배열의 첫 번째 항목을 91로 설정한다.

 "Bev"배열의 첫 번째 항목을 1 씩 증가시킨다. 

"Brian"키에 대한 배열의 첫 번째 항목을 설정하려고 한다. testScores dictionary에는 "Dave"및 "Bev"에 대한 키가 있기 때문에 처음 두 번의 호출이 성공한다. testScores dictionary에 "Brian"에 대한 키가 없으므로 세 번째 호출이 실패한다.


체이닝의 여러 단계 연결하기(Linking Multiple Levels of Chaining)

모델 내에서 프로퍼티, 메소드, 서브스크립에 옵셔널 체이닝을 여러 단계로 함께 연결 할 수 있다. 하지만, 값을 반환하기 위해, 옵셔널 체이닝의 여러 단계에 더 이상 옵셔널 단계를 추가하지 않는다.


달리 말하면 :
옵셔널이 아닌 타입을 가져오려고 시도하면, 옵셔널 체이닝에 의해 옵셔널이 될 것이다.
이미 옵셔널인 타입을 가져오려고 시도하면, 옵셔널 체이닝에 의해 더 이상 옵셔널이 되지 않을 것이다.
 
따라서 :
옵셔널 체이닝을 이용하여 Int값을 가져오려고 시도하면, 얼마나 많은 체이닝이 사용되는지와 상관없이, 언제나 Int?값이 반환된다.
비슷하게, 옵셔널 체이닝을 이용하여 Int?값을 가져오려고 시도하면, 얼마나 많은 체이닝이 사용되는지와 상관없이, 언제나 Int?값이 반환된다.

//아래는 옵셔널 체이닝 residence와 address의 두 레벨인 옵셔널 체이닝이 있다. 

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

// Prints "Unable to retrieve the address."

john.residence의 값은 현재 유효한 Residence인스턴스를 가지고 있지만, john.residence.address가 nil이어서 john.residence?.address?.street는 실패한다.

위의 예제에서 street 속성의 유형은 String? 이다. 
john.residence? .address? .street의 반환 값은 따라서 속성의 기본 옵션 유형에 추가로 두 가지 레벨의 옵셔널 체이닝이 적용 되더라도 String?이 된다.

실제 Address 인스턴스를 john.residence.address의 값으로 설정하고 address의 street 속성에 대한 실제 값을 설정하면 다중 레벨 옵셔널 체이닝을 통해 street 속성의 값에 액세스 할 수 있다.
 

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


john.residence의 값은 현재 유효한 Residence인스턴스를 포함하기 때문에, john.residence의 address프로퍼티에 설정을 시도는 성공할 것이다.

옵셔널 값을 반환하는 메소드 체이닝(Chaining on Methods with Optional Return Values)

옵셔널 값의 서브스크립트로부터 값을 가져오거나 설정하기 위해, 옵셔널 체이닝을 사용 할 수 있고, 서브스크립트 호출이 성공하는지 확인
 

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


옵셔널 타입의 값을 반환하는 메소드를 호출하기 위해, 옵셔널 체이닝을 사용할 수 있고, 필요에 따라, 메소드의 반환 값에 연결(chain)한다.
옵셔널 체이닝을 이용하여 Address클래스의 buildingIdentifier()메소드를 호출한다. 이 메소드는 String?타입의 값을 반환한다. 
위에서 설명한 것처럼, 옵셔널 체이닝 이후에 호출한 이 메소드의 궁극적인 반환 타입은 String?
 

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


반응형