Mobile/ios & swift

[Swift 4] Optional Chaining(2) - 옵셔널 체이닝을 이용하여 프로퍼티 접근하기

버리야 2018. 3. 19. 23:47
반응형

이 포스팅은 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



옵셔널 체이닝을 위한 모델 클래스 정의하기


옵셔널 체이닝을 사용하여, 한 단계 이상의 레벨에 해당하는 프로퍼티, 메소드, 서브스크립트 호출하여 사용 할 수 있다.

상호 관련된 타입의 복잡한 모델내에서 서브프로퍼티로 내려가는 것이 가능하고, 서브프로퍼티에서 프로퍼티, 메소드, 서브스크립트에 접근이 가능한지 확인 할 수 있다.


아래 예제는 다중 레벨 옵셔널 체인의 예를 포함하여 사용할 4개의 모델 클래스를 정의한다.



class Person {
    var residence: Residence?
}

//Residence클래스는 [Room]타입의 비어 있는 배열로 초기화된 rooms 변수 프로퍼티를 정의
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
        }
    }
}




옵셔널 체이닝을 이용하여 프로퍼티 접근하기(Accessing Properties Through Optional Chaining)


강제 언래핑 대안으로서의 옵셔널 체이닝(Optional Chaining as an Alternative to Forced Unwrapping)에서 설명했던것 처럼,

옵셔널 값의 프로퍼티에 접근하기위해 옵셔널 체이닝을 사용할 수 있고, 프로퍼티 접근이 성공하는지 확인한다.


새로운 Person인스턴스를 생성하고, 이전처럼 numberOfRooms프로퍼에 접근을 시도한다.


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

john.residence가 nil이기 때문에, 이전과 같은 방법으로는 옵셔널 체이닝 호출은 실패한다.



또한, 옵셔널 체이닝을 이용해서 프로퍼티의 값을 설정하는 것을 시도할 수 있다.

let someAddress = Address()

someAddress.buildingNumber = "29"

someAddress.street = "Acacia Road"

john.residence?.address = someAddress


이 예제에서는 john.residence가 현재 nil이므로 john.residence의 address 속성을 설정하려는 시도가 실패한다.



할당은 옵셔널 체인의 일부이므로 = 연산자의 오른쪽에있는 코드는 평가되지 않는다. 

앞의 예에서 상수에 액세스 할 때 side effect가 없기 때문에 someAddress가 평가되지 않는다는 것을 쉽게 알 수 없다.


아래 목록은 동일한 할당을 수행하지만 address를 작성하는 함수를 사용한다.

이 함수는 값을 반환하기 전에 "함수가 호출되었습니다."라는 메시지를 출력하여 = 연산자의 오른쪽이 평가되었는지 확인할 수 있다.

func createAddress() -> Address {

    print("Function was called.")

    

    let someAddress = Address()

    someAddress.buildingNumber = "29"

    someAddress.street = "Acacia Road"

    

    return someAddress

}

john.residence?.address = createAddress()

아무것도 출력되지 않았기 때문에, createAddress()함수가 호출되지 않았다.

반응형