객체 속성에 접근할 때 타입 안전하게 접근하는 방법 : KeyPath
- Swift4에서 도입
- 객체의 특정 속성에 대한 경로를 표현하는데 사용됨
- KeyPath를 통해 객체의 속성에 접근하면 컴파일 타임에 타입 체크가 이루어지기 때문에 안전한 코드 작성 가능
- KVO(Key-Value Observing)과 함께 사용되는 케이스가 있음
struct Person {
var name: String
var age: Int
}
let nameKeyPath = \Person.name
let ageKeyPath = \Person.age
let person = Person(name: "John", age: 30)
print(person[keyPath: nameKeyPath]) // "John"
print(person[keyPath: ageKeyPath]) // 30
// Root 타입은 생략이 가능
print(person[keyPath: \.age]) // 30
용례
- 함수형 프로그래밍 스타일
: 직접 프로퍼티를 호출하지 않고 KeyPath를 통해 비교 기준 지정 가능
let people = [
Person(name: "Alice", age: 24),
Person(name: "Bob", age: 27),
Person(name: "Charlie", age: 22)
]
let sortedByName = people.sorted(by: \.name)
let sortedByAge = people.sorted(by: \.age)
- KVO
class ObservablePerson: NSObject {
@objc dynamic var name: String
@objc dynamic var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
let observablePerson = ObservablePerson(name: "Eve", age: 28)
let observation = observablePerson.observe(\.name, options: [.old, .new]) { person, change in
print("Name changed from \(change.oldValue!) to \(change.newValue!)")
}
observablePerson.name = "Eva"
- KeyPath를 직접 정의하여 사용
struct Person {
var name: String
var age: Int
}
struct Class {
var yuk: Person
// KeyPath로 접근하지 않는 경우
func getYuk() -> Person {
return self.yuk
}
}
let yuk = PersonInfo(name: "yuk", age: 31)
let class = Class(yuk: yuk)
// Class의 메서드를 통해 갖고 오고 싶은 경우 getYuk를 구현 후 호출
print(class.getYuk())
// KeyPath를 통해 갖고 오고 싶은 경우 extension 구현
extension Class {
func getClass(keyPath: KeyPath<Self, Person>) -> Person {
self[keyPath: keyPath]
}
}
print(class.getClass(keyPath: \.yuk))
'iOS > Swift' 카테고리의 다른 글
[Swift/Xcode] 하나의 빌드 설정에 여러 xconfig을 등록하는 방법 (0) | 2024.07.27 |
---|---|
[Swift] 이미지 크기 Resize 방법 세 가지 (0) | 2024.07.20 |
[Swift] Coordinator 패턴으로 화면 전환 +DIContainer(Swinject) (0) | 2024.07.13 |
[Swift] Dictionary(grouping:by:) (0) | 2024.07.12 |