Mobile/ios & swift

[Swift 4] Optional Chaining(1) - 강제 언래핑 대안으로서의 옵셔널 체이닝

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

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




Optional Chaining

옵셔널 체이닝(Optional chaining)

현재 옵셔널이 nil이 될 수 있는 프로퍼티, 메소드, 서브스크립트를 조회하고 호출하는 과정


옵셔널에 값이 있으면, 프로퍼티, 메소드, 스크립트 호출은 성공이고, nil이면 nill을 반환한다.

여러개를 함께 연결 할 수 있고, 연결된 어떤 링크가 nil이면, 전체 체인(chain)은 실패하게 된다.




강제 언래핑 대안으로서의 옵셔널 체이닝(Optional Chaining as an Alternative to Forced Unwrapping)


옵셔널이 nil이 아닌 경우, 호출하길 원하는 프로퍼티, 메소드, 서브스크립트 옵셔널 값 뒤에 물음표(?)를 붙여서 옵셔널 체이닝을 지정한다.

이것은 값을 강제로 언래핑하기 위해 옵셔널 값 뒤에 느낌표(!)를 붙이는 것과 매우 비슷하다.

중요한 차이점은 옵셔널 체이닝은 옵셔널이 nil일때 우아하게 실패하며, 반면에 강제 언래핑은 옵셔널이 nil일때 실시간 오류가 발생한다.


이러한 사실을 반영하기 위해 옵셔널 체이닝은 nil값을 호출 할수 있으며, 옵셔널 체이닝 호출의 결과는 항상 옵셔널 값이며,

심지어는 프로퍼티, 메소드, 서브스크립트 조회하여 옵셔널이 아닌 값을 반환하더라도 마찬가지이다.

옵셔널 리턴 값을 옵셔널 체이닝 호출이 성공하거나(리턴된 옵셔널이 값을 가지고 있음)

체인(chain)에서 nil 값으로 인해 성공하지 못했는지(리턴된 옵셔널이 값은 nil) 여부를 확인할 수 있다.


특히, 옵셔널 체이닝 호출의 결과는 예상한 return 값과 같은 타입이지만, 옵셔널로 감싸져 있다.

옵셔널 체이닝으로 접근할때, 일반적으로 Int을 반환하는 프로퍼티는 Int?을 반환합니다.



아래 예제는 강제 언래핑과 옵셔널 체이닝이 어떻게 다른지 보여주는 예제.

class Person {
    var residence: Residence?
}

class Residence {
    var numberOfRooms = 1
}


let john = Person()
print(john.residence)

//Person인스턴스를 새로 생성하면, residence프로퍼티는 옵셔널이므로 기본적으로 nil로 초기화


let roomCount = john.residence!.numberOfRooms //값이 없는 residence를 강제 언래핑하니깐, 런타임 에러가 난다.

john.residence가 nil이 아닌 값이고 roomCount가 적절한 방의 갯수를 가지는 Int값을 설정 할때, 위의 코드는 성공한다.

하지만, 이 코드는 위에서 보는 것처럼, residence가 nil일때, 항상 런타임 오류가 발생.



옵셔널 체이닝(Optional chaining)은 numberOfRooms 값에 접근하는 방법을 제공한다. 옵셔널 체이닝을 사용하기 위해, 느낌표(!)위치에 물음표(?)를 사용


if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")  //여기가 실행된다.
}

이 예제는 Swift가 residence 옵셔널 프로퍼티에서 "체인(chain)"은 residence가 존재하면 numberOfRooms의 값을 가져오는 것을 말한다.


numberOfRooms에 접근을 시도하는 것은 실패할 가능성이 있기 때문에, 옵셔널 체이닝은 Int? 타입의 값이나 옵셔널 Int값을 반환 하려고 한다.

위의 예제처럼, residence가 nil일때, 옵셔널 Int는 nil이 될 것이며, numberOfRooms에 접근하는 것이 가능하지 않다는 사실을 알려준다.

옵셔널 Int는 옵셔널 바인딩을 통해서 integer를 언래핑을 하고 roomCount 변수에 옵셔널이 아닌 값을 할당한다.



numberOfRooms에 접근하려는 시도는 잠재적으로 실패하기때문에 옵셔널 체이닝은 Int? 또는 옵셔널 Int 타입의 값을 반환하도록 해야한다. 

residence는 nil일때 옵셔널 Int는 또한 nil이고, numberOfRooms에 접근할 수 없다는 사실을 반영한다.


numberOfRooms이 옵셔널 Int가 아닐지라도, 옵셔널 체인은 numberOfRooms가 항상 Int 대신 Int?를 반환한다.



Residence 인스턴스를 john.residence에 할당하여 더 이상 nil 값을 갖지 않게 할 수 있다.

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



반응형