Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- ribs
- tableView
- combine
- rxswift
- 클린 코드
- 스위프트
- map
- 리팩토링
- HIG
- Refactoring
- Observable
- RxCocoa
- swift documentation
- ios
- 애니메이션
- UITextView
- uitableview
- Xcode
- 리펙터링
- collectionview
- MVVM
- SWIFT
- UICollectionView
- 리펙토링
- swiftUI
- uiscrollview
- Protocol
- Human interface guide
- clean architecture
- Clean Code
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - Swift] KVC, KeyPath, DynamicMemberLookup 개념 본문
KVC와 KeyPath
- KVC(Key - Value coding) - 객체의 값을 직접 가져오지 않고 KeyPath를 이용해서 간접적으로 데이터를 가져오거나 사용 (key는 string)
- KeyPath
- 값에 대한 참조가 아닌, 프로퍼티를 참조
struct Person {
var name: String
}
let person = Person(name: "jake")
person.name // 값을 참조
person[keyPath: \.name] // 프로퍼티를 참조
- KeyPath 종류
- AntyKeyPath: 타입이 지워진 KeyPath
- PartialKeyPath: 부분적으로 타입이 지워진 KeyPath
- KeyPath: 읽기 전용
- WriatableKeyPath: 읽기, 쓰기 가능
- ReferenceWritableKeyPath: 클래스의 인스턴스에 사용 가능, 변경 가능한 모든 프로퍼티에 대한 읽기와 쓰기 가능
- KeyPath의 특징 - 프로퍼티 분류가 외부에서 선택이 가능
// KeyPath 없이 child의 name을 가져오는 경우, getChild1Name(), getChild2Name()
struct Parent {
var child1: Child
var child2: Child
func getChild1Name() -> String {
child1.name
}
func getChild2Name() -> String {
child2.name
}
}
struct Child {
var name: String
}
let parent = Parent(child1: Child(name: "1"), child2: Child(name: "2"))
parent.getChild1Name()
parent.getChild2Name()
(KeyPath 사용한 경우 - 키패스는 프로퍼티를 구분할 수 있으므로 키패스사용)
struct Parent {
var child1: Child
var child2: Child
func getChildName(keyPath: KeyPath<Parent, Child>) -> String {
self[keyPath: keyPath].name
}
}
struct Child {
var name: String
}
let parent = Parent(child1: Child(name: "1"), child2: Child(name: "2"))
parent.getChildName(keyPath: \.child1) // 값에 대한 참조가 아닌 프로퍼티를 참조
parent.getChildName(keyPath: \.child2)
- KeyPath 타입: <Root타입, Root타입이 가지고 있는 인스턴스 타입>
public class KeyPath<Root, Value> : PartialKeyPath<Root> {
}
dynamic member lookup
- 인덱싱은 원래 arr[i]처럼 접근하지만, dynamic lookup은 닷 ‘.’으로 접근할수 있는 기능
(적용 전 - [”jake”]와 같이 괄호안에 인덱싱으로 접근)
struct Person1 {
var info: [String: String] // name: gender
subscript(name: String) -> String? {
return self.info[name]
}
}
let person1 = Person1(
info: ["jake": "man1"]
)
print(person1["jake"]) // Optional("man1")
(적용 - 점으로 접근)
- @dynamicMemberLookup
- subscript와 dynamicMember를 명시하는 subscript 정의
@dynamicMemberLookup
struct Person2 {
var info: [String: String] // name: gender
subscript(dynamicMember name: String) -> String? {
return self.info[name]
}
}
let person2 = Person2(
info: ["jake": "man2"]
)
print(person2.jake) // Optional("man2")
KeyPath + dynamicLookup 사용하여 syntatic sugar 만들기
- keyPath와 dynamicLookup 사용
- keyPath: 프로퍼티 별 접근이 가능
- dynamicLookup: ‘.’ dot으로 접근 가능
ex) parent안에 있는 child의 name접근 시, parent.name로 접근하기
(일반적인 경우 - parent.child.name으로 접근)
struct Parent {
var child: Child
}
struct Child {
var name: String
var company: String
}
let parent = Parent(child: Child(name: "1", company: "c1"))
print(parent.child.name)
(KeyPath + dynamicLookup 사용 - parent.name 접근)
1단계) subscript안에 keyPath를 주입받도록 구현
- parent[\.company]로 접근 가능 (KeyPath의 루트가 Child 형태이므로)
struct Parent {
var child: Child
subscript(keyPath: KeyPath<Child, String>) -> String {
child[keyPath: keyPath]
}
}
struct Child {
var name: String
var company: String
}
let parent = Parent(child: Child(name: "1", company: "c1"))
print(parent[\\.company])
2단계) dynamicMemberLookup을 사용하여 대괄호 대신에 dot ‘.’으로 접근 가능하도록 구현
- parent[\.company]에서 parent.company로 접근 가능 (매우 간편하게 접근)
@dynamicMemberLookup
struct Parent {
var child: Child
subscript(dynamicMember keyPath: KeyPath<Child, String>) -> String {
child[keyPath: keyPath]
}
}
struct Child {
var name: String
var company: String
}
let parent = Parent(child: Child(name: "1", company: "c1"))
print(parent.company)
요약
- keyPath: 값에 대한 참조가 아닌, 프로퍼티를 참조
- dynamic member lookup: 대괄호 []로 접근하는 기호를 dot '.'으로 접근할 수 있게끔 하는 방법
- keyPath + dynamic member lookup: Parent가 가지고 있는 Child이 프로퍼티를 외부에서 쉽게 접근 가능 (parent.childName)
* 참고
'iOS 응용 (swift)' 카테고리의 다른 글
Comments