티스토리 뷰
안녕하세요 :) Zedd입니다.
오늘은 KVC에 대해서 공부해보겠습니다.
# KVC
- Key-Value Coding 의 약자
- 객체의 값을 직접 가져오지않고, Key 또는 KeyPath 를 이용해서 간접적으로 데이터를 가져오거나 수정하는 방법
- key는 String
- key는 일반적으로 객체에 정의된 accessor method 또는 인스턴스 변수의 "이름"
- key는 특정 규칙을 따라야함 - ASCII로 인코딩 되고, 소문자로 시작해야하며, 공백이 없어야한다.
예를들어
person객체에 address프로퍼티가 있고,
address프로퍼티는 town프로퍼티를 가지고 있다고 생각해봅시다.
id address = [person valueForKey:@"address"];
id town = [address valueForKey:@"town"];
그럼 이렇게 String key를 이용하여 프로퍼티에 접근할 수 있게 됩니다.
id town = [person valueForKeyPath:@"address.town"];
이렇게 keypath로도 접근이 가능합니다. address.town으로 바로 접근할 수 있게 됐죠
key를 가지고 value를 가져오는 그런 코딩 방식(?)을 KVC라고 하는 것 같습니다.
근데 Swift에서 이걸 해보려고 하면 살짝 상상이 안가죠.
struct Address {
var town: String
}
struct Person {
var address: Address
}
let address = Address(town: "어쩌구")
let zedd = Person(address: address)
print(zedd.address)
print(zedd.address.town)
왜냐면 나는 String으로 가져오지 않고..
그냥 zedd.address.town이런식으로 가져오니까..그러니까 객체의 값을 "직접"가져오는 것이 일반적입니다.
KVC는 key또는 keyPath를 이용하여 간접적으로 값을 가져오는 방식이었는데..
Swift에서 KVC를 하려면 어떻게 할 수 있을까요?
struct Address {
var town: String
}
struct Person {
var address: Address
}
let address = Address(town: "어쩌구")
let zedd = Person(address: address)
let zeddAddress = zedd[keyPath: \.address]
let zeddTown = zedd[keyPath: \.address.town]
print(zeddTown) // 어쩌구
Swift에서도 이렇게 keypath를 이용하여 간접적으로 value를 가져올 수 있습니다.
Objc코드에서는 값을 가져오는것만 했는데, 수정도 가능합니다.
struct Address {
var town: String
}
struct Person {
var address: Address
}
let address = Address(town: "어쩌구")
var zedd = Person(address: address)
zedd[keyPath: \.address.town] // 어쩌구
zedd[keyPath: \.address.town] = "바보"
zedd[keyPath: \.address.town] // 바보
zedd.address.town // 바보
이렇게 말이죠.
위 코드에서 보면 \.address.town가 반복되어 나타나는 것을 볼 수 있습니다.
keyPath를 만들어 놓고 여러군데서 쓰면 좋을텐데요.
# KeyPath를 만드는 방법
Keypath를 만드는 syntax입니다.
let writableKeyPath = \Person.address.town
zedd[keyPath: writableKeyPath] // 어쩌구
zedd[keyPath: writableKeyPath] = "바보"
zedd[keyPath: writableKeyPath] // 바보
이렇게 keyPath를 만들어 사용하고싶은 곳에 사용하면 됩니다.
Q : \.address.town으로 했는데 왜 \Person.address.town으로 해줘야해?
A : zedd가 이미 Person타입이므로 타입을 생략할 수 있었습니다.
# KeyPath의 종류
Keypath의 종류에는 위와같은것들이 있는데요,
AnyKeyPath - 타입이 지워진 KeyPath
PartialKeyPath - 부분적으로 타입이 지워진 KeyPath
✔️ KeyPath - Read-only
✔️ WritableKeyPath - value type 인스턴스에 사용 가능. 변경 가능한 모든 프로퍼티에 대한 read & write access 제공
✔️ ReferenceWritableKeyPath - 클래스의 인스턴스에 사용 가능. 변경 가능한 모든 프로퍼티에 대한 read & write access 제공.
struct Address {
var town: String
}
struct Person {
var address: Address
}
let writableKeyPath = \Person.address.town
zedd[keyPath: writableKeyPath] // 어쩌구
zedd[keyPath: writableKeyPath] = "바보"
zedd[keyPath: writableKeyPath] // 바보
자..제가 writableKeypath라고 이름을 지어줬는데.. WritableKeyPath타입입니다.
✔️ WritableKeyPath - value type 인스턴스에 사용 가능. 변경 가능한 모든 프로퍼티에 대한 read & write access 제공
왜냐면..
struct Address {
var town: String
}
let writableKeypath = \Person.address.town
town이 var이기 때문입니다. (변경가능한 모든 프로퍼티에 대한..)
만약 town이 let이라면 수정할 수 없으므로
더이상 WritableKeyPath가 아닌 그냥 KeyPath타입이 되게 됩니다.
당연히 Read-only이니 변경도 안됩니다.
let이면 자동으로 KeyPath타입을.
var면 자동으로 WritableKeyPath타입을 넣으니 참고해주세요.
자...위 예제들에서 Person과 Address는 모두 struct(value type)였는데요.
이걸 class(reference type)로 바꿔보겠습니다.
class Address {
var town: String
init(town: String) {
self.town = town
}
}
class Person {
var address: Address
init(address: Address) {
self.address = address
}
}
let referenceWritableKeyPath = \Person.address.town
이때는 저 keypath가 자동으로 ReferenceWritableKeyPath타입이 됩니다.
✔️ ReferenceWritableKeyPath - 클래스의 인스턴스에 사용 가능. 변경 가능한 모든 프로퍼티에 대한 read & write access 제공.
여기서도 town이 let이면 KeyPath타입이 되겠죠?
참고
developer.apple.com/wwdc17/212
developer.apple.com/library/archive/documentation/Cocoa/Conceptual/KeyValueCoding/index.html
'Swift' 카테고리의 다른 글
Property Wrapper (2) | 2021.03.07 |
---|---|
Key-Value Observing(KVO) in Swift (2) | 2021.03.01 |
Unowned Optional References (11) | 2021.02.22 |
Swift ) ARC / Strong Reference Cycle 해결 방법(weak, unowned) (4) | 2021.02.18 |
Swift ) 정렬 (3) - Sort by multiple criteria (1) | 2020.11.24 |
- Accessibility
- np-hard
- 피아노
- swift3
- SwiftUI
- swift 공부
- Combine
- swift sort
- swift delegate
- swift tutorial
- IOS
- Xcode
- WWDC
- np-complete
- 스위프트 문법
- UIBezierPath
- github
- 제이슨 파싱
- WKWebView
- FLUTTER
- Git
- fastlane
- iOS delegate
- actor
- WidgetKit
- 스위프트
- 회고
- swift array
- ios 13
- Swift
- Total
- Today
- Yesterday