clamp
Clamp
clamp
글쓰기 관리
전체 방문자
오늘
어제
  • 분류 전체보기 (509)
    • IOS (85)
    • SwiftUI+TCA+Combine (9)
    • RxSwift + MVVM (56)
    • Clean Architecture (12)
    • SWIFT (56)
    • iOS - TDD (2)
    • 디자인패턴 (4)
    • CS (56)
      • 알고리즘 (29)
      • 운영체제 (15)
      • 자료구조 (2)
      • 네트워킹 (4)
      • 기타 (6)
    • 회고 (0)
    • Firebase (18)
    • SwiftUI (10)
    • iOS - UIKit (11)
    • iOS - 오픈소스 (6)
    • 코딩테스트 (166)
      • 프로그래머스 (164)
    • 정보처리기사 (14)
    • GitHub (2)
글쓰기 / 관리자

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • uikit
  • Q
  • Swift
  • ㅅ

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
clamp

Clamp

[Swift] #keyPath
SWIFT

[Swift] #keyPath

2023. 3. 20. 14:30

#keyPath와 #selector는 문법적인 내용이 아닌 Framework와 관련된 내용이다.

objc부터 쓰이던 기술임에도 불고하고 여전히 쓰이던 내용이다. framework 내부적인 메커니즘에 여전히 objc를 떼어놓고 사용할 수 없는 몇 가지 기술들이 있기 때문에 여전히 쓰인다. 물론 버려져야함..

 

 

#keyPath

person.name
	⬇️
"person.name" or person["name"] 이런식으로 접근하면 안될까?

 

키경로(문자열처럼 쉽게 만들 수 있는 인스턴스)/ 문자열로 속성에 접근하는 것이 편하지 않을까?
라는 생각으로 시작된 문법??

 

이런 문법이 필요한 예를 들어보자.

class Restaurant{
    var name: String
    var affiliate: Snack
    
    init(name: String, affiliate: Snack){
        self.name = name
        self.affiliate = affiliate
    }
}

class Snack{
    var staffname: Person
    
    init(staffname: Person){
        self.staffname = staffname
    }
}

class Person{
    var name: String
    init(name: String){
        self.name = name
    }
}

let person = Person(name: "clamp")
let snack = Snack(staffname: person)
let restaurant = Restaurant(name: "master", affiliate: snack)

// Restaurant는 Snack클래스를 갖고있고,
// Snack클래스는 Person클래스를 갖고있고
// Person클래스는 name을 갖고있다.
// 최종적으로 알고싶은 Person의 name까지 접근하기 위해 써야하는 코드가 늘어난다면?
let clampname = restaurant.affiliate.staffname.name   // clamp

let namePath = \Restaurant.affiliate.staffname.name  // 미리 경로를 지정[keyPath]

restaurant[keyPath: namePath] // 딕셔너리방식으로 접근

 

미리 경로를 만들어 놓고 그 경로를 통해서 clamp까지 접근할 수 있었다.

만약 clamp와 같은 경로까지 무수히 많은 인스턴스에대해 접근해야한다면 일일이 .점접근문법을 써서 직접적으로 접근한다.

하지만 키패스를 사용하면 간접적으로 접근할 수 있다.

 

 

직접적인 접근

let clampname = restaurant.affiliate.staffname.name

 

간접적인 접근

let namePath = \Restaurant.affiliate.staffname.name

restaurant[keyPath: namePath]

경로를 정해놓고 간접적으로 접근할 수 있다.

 

 

keyPath 타입

 - AnyKeyPath                             : 어떤 속성인지 특정되지 않음(보통, 함수 파라미터형식으로만 사용)
 - PartialKeyPath<Root>                   : 타입에 대한 키패스(예를 들어 배열 같은 것으로 묶을때 사용)
 - KeyPath<Root, Value>                   : 타입과 (읽기)속성에 대한 키패스(구조체)
 - WritableKeyPath<Root, Value>           : 타입과 읽기/쓰기 가능한 속성에 대한 키패스(구조체)
 - ReferenceWritableKeyPath<Root, Value>  : 클래스의 타입과 읽기/쓰기 가능한 속성에 대한 키패스

 

 

 

결론

키패스 == 경로

 

 


+ 추가 예전버전, Objective-C의 방식, #keyPath(타입.속성) 방식

// NSObject클래스를 상속해야함(구조체 지원 안함)
// - NSObject에 value(forKey:)메서드가 구현이 되어있기 때문
// - 속성에도 @objc를 붙여야함
// - 사용시, 구체적타입으로 다시 타입캐스팅해서 사용해야함
 
class Person: NSObject {
    @objc var name: String
    init(name: String) {
        self.name = name
    }
}

let person2 = Person(name: "clamp")
person2.name


let gjName = person2.value(forKey: "name") as? String
let gjName2 = person2.value(forKeyPath: #keyPath(Person.name)) as? String


let path = #keyPath(Person.name)
let gjName3 = person2.value(forKeyPath: path) as? String

 


+추가 키패스 경로를 추가하는 방법

// 타겟 \Restaurant.affiliate.staffname.name

let namePath = \Restaurant.affiliate.staffname // 어머 name을 빼먹었네

let newNamePath = namePath.appending(path: \.name) //추가
저작자표시 비영리 동일조건 (새창열림)
    'SWIFT' 카테고리의 다른 글
    • [Swift] available 키워드
    • [Swift] #selector(셀렉터)
    • [Swift] 디버깅(테스트/검증)함수 assert, precondition
    • [Swift] Never타입과 fatalError()
    clamp
    clamp
    주니어 iOS개발자의 발악!!!!!!!

    티스토리툴바