궁금한 내용을 검색해보세요!
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
서근 개발노트
티스토리에 팔로잉
SWIFT/Grammar

Swift : 기초문법 [프로퍼티#5 - 키 경로 KeyPath]

서근
QUOTE THE DAY

“ 책 보고 따라 해도 안된다고, 스스로 자책하지 마라. 진짜 멍청이들은 일반인들이 사용할 수 없도록 하드웨어와 소프트웨어를 만든 사람들이다. 사람들이 컴퓨터를 사주는데도 말이다. 우리는 그들을 컴퓨터 전문가라고 부른다. ”

- Walter Mossberg (월터 모스버그)
Written by SeogunSEOGUN

Swift : 기초문법 [프로퍼티#5 - 키 경로 KeyPath]

본 게시글은 Swift : 기초문법 [프로퍼티#5 - 키 경로 KeyPath]yagom님과Swift : 기초문법 [프로퍼티#5 - 키 경로 KeyPath]Zedd0202님의 게시글을 참고하여 작성되었습니다.

 

키 경로 KeyPath

객체의 값을 바로 꺼내오는 것이 아닌, Key 또는 KeyPath 를 이용해서 간접적으로 프로퍼티 위치 참조나 데이터를 가져오거나 수정하는 방법이다.

 

키 경로를 사용해 간접적으로 특정 타입의 어떤 프로퍼티 값을 가리켜야 할지 미리 지정해 두고 사용 가능. 여기서 경로는 프로퍼티 이름이라고 생각하면 된다.

 

키 경로는 역슬래시( \ ) 와 타입, 마침표( . ) 경로로 구성

swift
UNFOLDED
class Person {
var name: String
init(name: String) {
self.name = name
}
}
struct Stuff {
var name: String
var owner: Person
}
print(type(of: \Person.name)) //ReferenceWritableKeyPath<Person, String>
print(type(of: \Stuff.name)) //WritableKeyPath<Stuff, String>

키 경로는 기존 키 경로에 하위 경로를 덧붙일 수도 있다.

swift
UNFOLDED
let keyPath = \Stuff.owner
let nameKeyPath = keyPath.appending(path: \.name)

또, 각 인스턴스 keyPath 서브 스크립트 메서드에 키 경로를 전달해 프로퍼티에 접근도 가능하다.

swift
UNFOLDED
struct Address {
var town: String
}
struct Person {
var address: Address
}
let address = Address(town: "한옥마을")
let Seogon = Person(address: address)
let SeogonAddress = Seogon[keyPath: \.address] //Address(town: "한옥마을")
let SeogonTown = Seogon[keyPath: \.address.town] //한옥마을

키 경로 만드는 법

Swift : 기초문법 [프로퍼티#5 - 키 경로 KeyPath] - 키 경로 KeyPath - 키 경로 만드는 법
출처 : https://samwize.com/ WWDC 2017

swift
UNFOLDED
class Person {
let name: String
init(name: String) {
self.name = name
}
}
struct Stuff {
var name: String
var owner: Person
}
let seogun = Person(name: "서근")
var iPhone = Stuff(name: "아이폰", owner: seogun)
let referenceWritableKeyPath = \Stuff.name
iPhone[keyPath: referenceWritableKeyPath] //아이폰

이런 식으로 키 경로를 만들어서 사용하고 싶은 곳에 사용 가능! 예를 들자면 아래와 같다

swift
UNFOLDED
class Person {
let name: String
init(name: String) {
self.name = name
}
}
struct Stuff {
var name: String
var owner: Person
}
let seogun = Person(name: "서근")
let cheolsu = Person(name: "철수")
let iPhone = Stuff(name: "아이폰 12 mini", owner: seogun)
var Macbook = Stuff(name: "맥북프로", owner: cheolsu)
let airPod = Stuff(name: "에어팟 프로", owner: seogun)
let stuffNameKeyPath = \Stuff.name
let ownerKeyPath = \Stuff.owner
// ownerKeyPath의 owner은 class Person을 참조하고 있기때문에
// \Stuff.owner.name 과 같은 표현
let ownerNameKeyPath = ownerKeyPath.appending(path: \.name)
print(iPhone[keyPath: stuffNameKeyPath]) //아이폰 12 mini
print(Macbook[keyPath: stuffNameKeyPath]) //맥북 프로
print(airPod[keyPath: stuffNameKeyPath]) //에어팟 프로
print(iPhone[keyPath: ownerNameKeyPath]) //서근
print(Macbook[keyPath: ownerNameKeyPath]) //철수
print(airPod[keyPath: ownerNameKeyPath]) //서근
//키 경로와 서브스크립트를 이용해 프로퍼티에 접근해 값을 변경할 수 있음
//Macbook은 변수로 선언 했기 때문에 가능
Macbook[keyPath: stuffNameKeyPath] = "맥북 M1"
print(Macbook[keyPath: stuffNameKeyPath]) //맥북 M1
Macbook[keyPath: ownerKeyPath] = seogun
print(Macbook[keyPath: ownerNameKeyPath]) //서근
//반대로 상수로 선언한 타입과 읽기 전용 프로퍼티는 값을 바꿔줄 수 없음
iPhone[keyPath: stuffNameKeyPath] = "아이폰 13 pro"
//error : Cannot assign through subscript: 'iPhone' is a 'let' constant
seogun[keyPath: \Person.name] = "라쿤"
//error : 키 경로가 읽기 전용입니다.

KeyPath 종류

Swift : 기초문법 [프로퍼티#5 - 키 경로 KeyPath] - 키 경로 KeyPath - KeyPath 종류

WritableKeyPath

swift
UNFOLDED
struct Person {
var name: String
}
struct Stuff {
var owner: Person
}
let writableKeypath = \Stuff.owner.name

personname이 변수 이기 때문에 변경 가능한 모든 프로퍼티에 대한 read & write access를 제공하기 때문에 writableKeyPath가 된다. 만약 name이 상수이면 수정이 불가(Read-only) 하므로 WritableKeyPath가 아닌 일반적인 KeyPath 타입이 된다. 

Swift : 기초문법 [프로퍼티#5 - 키 경로 KeyPath] - 키 경로 KeyPath - KeyPath 종류 - WritableKeyPath

ReferenceWritableKeyPath

swift
UNFOLDED
class Person {
var name: String
init(name: String) {
self.name = name
}
}
class Stuff {
var name: String
var owner: Person
init(name: String, owner: Person) {
self.name = name
self.owner = owner
}
}
let seogun = Person(name: "서근")
var iPhone = Stuff(name: "아이폰", owner: seogun)
let referenceWritableKeyPath = \Stuff.name
iPhone[keyPath: referenceWritableKeyPath] //아이폰

위에서 사용한 코드는 class를 사용하고 있기 때문에 자동으로 ReferenceWritableKeyPath 타입이 됨. 

Swift : 기초문법 [프로퍼티#5 - 키 경로 KeyPath] - 키 경로 KeyPath - KeyPath 종류 - ReferenceWritableKeyPath

 

읽어주셔서 감사합니다🤟

 

 


잘못된 내용이 있으면 언제든 피드백 부탁드립니다.


서근


위처럼 이미지 와 함께 댓글을 작성할 수 있습니다.