apple/Docs, iOS, Swift

Swift KeyPath 정리

lgvv 2024. 8. 28. 01:23

Swift KeyPath 정리

 

Realm의 @objc dynamic으로 사용하는 이유, property wrapper의 다채로운 활용 등 KeyPath를 이해하면 Swift 언어의 발전을 이해하는데 도움.

 

KeyPath란?

  • KeyPath 표현식은 특정 타입의 속성(property) 또는 서브스크립트(subscript)를 참조.
  • KeyPath 표현식은 주로 키-값 관찰과 같은 동적 프로그래밍 작업에서 사용.
  • KeyPath 표현식은 다음과 같은 형태를 가짐.
     

사용 형태

\<#type name#>.<#path#>


 
샘플 코드

import SwiftUI
 
class Person: NSObject {
    @objc var name: String
    @objc var age: Int
    
    @objc dynamic var hp: Int = 100
    
    var mp: Int = 1 {
        willSet { print(newValue) }
        didSet { print(oldValue) }
    }
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
}
 
struct KeyPathExampleView: View {
    var body: some View {
        VStack(spacing: 30) {
            Button {
                kvc()
            } label: {
                Text("kvc")
            }
            
            Button {
                kvo()
            } label: {
                Text("kvo")
            }
        }
    }
    
    let person = Person(name: "John", age: 30)
 
    func kvc() {
        // KVC를 사용하여 값 가져오기
        if let name = person.value(forKey: "name") as? String,
           let age = person.value(forKey: "age") as? Int
        {
            print("Name: \(name) Age: \(age)")  // 출력: Name: John
        }
        
        // KVC를 사용하여 값 설정하기
        person.setValue(35, forKey: "age")
        print(person.age)  // 출력: 35
        print(person[keyPath: \.age])  // 출력: 35
    }
    
    func kvo() {
        person.observe(
            \.hp,
             options: [.initial, .old, .new, .prior]
        ) { person, observedChange in
 
            if observedChange.isPrior {
                    print("About to change: \(String(describing: observedChange.oldValue))")
                } else {
                    print("Changed from \(String(describing: observedChange.oldValue)) to \(String(describing: observedChange.newValue))")
                }
        }
        person.hp = 20
        person.mp = 10
    }
}
 
#Preview {
    KeyPathExampleView()
}

 
KeyPath를 사용하는 것과 직접 접근하는 것의 차이

직접접근

  • 설명: 점 표기법을 사용하여 객체의 속성에 직접 접근. 이 방법은 가장 일반적인 방식으로, 컴파일 타임에 속성의 존재와 타입이 확정.
  • 유연성: keyPath를 변수로 저장하거나 함수에 전달할 수 있음. 따라서 런타임에 어떤 속성에 접근할지 동적으로 결정할 수 있음.
  • 활용 범위: 주로 복잡한 데이터 구조에서 여러 속성에 대해 동일한 연산을 적용해야 하거나, 속성을 동적으로 접근해야 하는 경우에 유용

KeyPath 접근

  • 설명: KeyPath를 사용하여 객체의 속성에 접근하는 방식. 이 방법은 런타임에 KeyPath를 통해 속성에 간접적으로 접근할 수 있음. KeyPath는 경로를 나타내는 타입 안전한 객체.
  • 유연성: keyPath를 변수로 저장하거나 함수에 전달할 수 있음. 따라서 런타임에 어떤 속성에 접근할지 동적으로 결정할 수 있음.
  • 활용 범위: 주로 복잡한 데이터 구조에서 여러 속성에 대해 동일한 연산을 적용해야 하거나, 속성을 동적으로 접근해야 하는 경우에 유용.

 

 

(참고)

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/expressions/?source=post_page-----5956923a8976--------------------------------#Key-Path-Expression

 

Documentation

 

docs.swift.org