관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] dynamic member lookup, @dynamicMemberLookup, dot으로 이름 접근, map. 본문

iOS 응용 (swift)

[iOS - swift] dynamic member lookup, @dynamicMemberLookup, dot으로 이름 접근, map.

jake-kim 2021. 12. 23. 23:42

* KeyPath부터 구체적인 dynamic member lookup 개념은 이글 참고

dynamic member lookup

출처: https://docs.swift.org/swift-book/ReferenceManual/Attributes.html

  • @dynamicMemberLookup 키워드를 class, structure, enum, protocol에 적용하여 subscript(dynamicMember:)를 필수로 구현하게하여 런타임시점에 이름으로 dot ‘.’키워드로 접근 가능하도록 하는 방법
  • dot ‘.’ 키워드 사용하여 이름으로 접근 가능
  • 주의: extension에는 @dynamicMemberLookup 적용 불가

ex) dyanmicMemberLookup을 사용하지 않고 subscript 구현

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")

ex) dyanmicMemberLookup을 사용하여 subscript 구현하면 dot '.' 으로 접근 가능

@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")

ex) Keypath를 subscript하여, Observable의 Value에 바로 접근

  • dynamicMemberLookup을 안쓴 경우 - person3.map(\.name)
  • dynamicMemberLookup을 쓴 경우 - person3.name
// Observable
// @dynamicMemberLookup 키워드는 extension에 선언하지 못하므로 따로 protocol 선언 -> Observable에서 해당 프로토콜 준수하여 구현
@dynamicMemberLookup
protocol DynamicMemberLookupObservableType {
  associatedtype Root
  /// Value 타입 - Observable<Value>
  subscript<Value>(dynamicMember keyPath: KeyPath<Root, Value>) -> Observable<Value> { get }
}

extension Observable: DynamicMemberLookupObservableType {
  subscript<Value>(dynamicMember keyPath: KeyPath<Element, Value>) -> Observable<Value> {
    self.map { $0[keyPath: keyPath] }
  }
}

struct Person3 {
  var name: String
  var gender: String
}

let person3 = self.exampleObservableDynamicMember()
let name = person3.name.asObservable().subscribe { print($0) } // next(jake)

 

Comments