KeyPath 번역하자면 "특정 루트 유형에서 특정 결과 값 유형으로의 키 경로"
다시 쉽게 이해하자면
특정 루트 유형(내가 알고 싶은 값을 담고있는 타입)에서 특정결괏값 유형(내가 알고 싶은 값)의 경로
class KeyPath<Root, Value>
class KeyPath<내가 알고 싶은 값을 가지고 있는 타입, 내가 알고 싶은 값의 타입>
예시
struct Video {
let ratio: Ratio
var quality: Float
}
struct Ratio {
var horizontal: Int
var vertical: Int
}
var gameVideo = Video(
ratio: .init(
horizontal: 16,
vertical: 9),
quality: 720
)
여기서 Ratio의 값을 접근해야한다면
1. 프로퍼티에 접근한다
2. 함수로 접근한다
3. KeyPath를 사용한다.
프로퍼티에 접근한다
2. 함수로 접근한다
func getVideoRatio(for video: Video) -> Ratio {
return video.ratio
}
여기서 1과 2는 별차이가 없다. 1번은 내부에서 프로퍼티에서 Gette를 부르고 함수 또한 안에서 프로퍼티를 반환
3. KeyPath를 활용한다.
let 내가 알고싶은 값의 경로
== 경로정보(\), 내가 알고 싶은 값을 가지고 있는 타입(Video), 내가 알고 싶은 값의 타입의 프로퍼티(Video.ratio)
== let ratioKeyPath = \Video.ratio
gameVideo[keyPath: gameKeyPath]
1,2 와 같이 값을 가져올 수 있습니다.
또한 KeyPath는 알고 싶은 프로퍼티에 대한 속성과 타입에 따라서 분류가 됩니다.
struct Video {
var ratio: Ratio // let -> var
var quality: Float
}
let을 var바꾼다면 KeyPath에서 WritableKeyPath로 바뀌게 됩니다.
여기까지 간단하다면 간단하게 KeyPath에 대해서 알아보았습니다.
이번엔 드디어 함수측면에서 KeyPath를 알아보도록 할게요.
let ratioKeyPath = \Video.ratio
gameVideo[keyPath: gameKeyPath]
video.name은 내부에서 name프로퍼티의 getter함수가 실행되면 Video의 name(String)을 반환하죠?
2번째 함수도 타입을보자면
(Video) -> String 이죠!
여기서 Video타입에 KeyPath를 사용했지만 범용타입에 대한 KeyPath를 사용해 보도록 하겠습니다.
func get<Root, Value>(_ keyPath: KeyPath<Root, Value>) -> (Root) -> Value {
return { root in root[keyPath: keyPath] }
}
Generic 타입으로 KeyPath의 Root와 Value를 받도록 하였고,
반환타입을 (Root) -> Value 함수타입을 반환하도록 하였습니다.
반환하는 코드를 보자면 KeyPath와 같은 Root타입을 받아서 해당 Root를 매개변수로 받은 KeyPath로 접근하여 Value를 가져오는 함수 타입을 반환합니다.
이제 Keypath도 get함수를 통해서 (Video) -> String를 반환하므로 KeyPath를 함수로 활용할 수 있게 되었습니다.
KeyPath는 존재하지 않는 경로에 대해선 컴파일러 단계에서 오류를 뱉어내기에 안전한 코딩이 가능합니다.
언젠간 이러한 KeyPath의 장점과 특징 그리고 오늘 만들어본 함수타입으로 변환하는 함수를 활용할 날이 있을 것 같습니다!
그럼 끄ㅌ!
참조
'Swift' 카테고리의 다른 글
Swift에서 Map 만들어보기 (1) | 2023.05.03 |
---|---|
Swift Optional unWrapping을 좀 더 간편하게 쓰는 법 (0) | 2023.04.20 |
Array에서 중복 제거하는 방법 (0) | 2023.04.19 |
Array의 index를 안전하게 처리하는 방법 (2) | 2023.04.18 |
KeyPath (2) | 2023.01.16 |