Dynamic Member Lookup - ehrldyd15/Swift_Skills GitHub Wiki

Dynamic Member Lookup

class, struct, enum, protocol에 사용 가능하다.

subscript(dynamicMemberLookup :) 메소드를 구현해야 함.

만약 dynamicMemberLookup을 사용하는 타입이 있다면 런터임시 확인되는 임의의 이름에 대하여 dot syntax를 제공해 준다.

1. Subscripts

Subscripts는 첨자이며 이를 이용하여 index로 값을 설정하고 값을 가져올 수 있다.

var arr = ["DKY", "Mario"]
arr[0] // DKY
arr[1] = "Json"

Swift의 Collection이 Subscript를 요구하고 있기 때문에 위의 문법이 가능하다.

public protocol Collection: Sequence {
    ...
    subscript(position: Index) -> Element { get }
}

Array, Dictionary, Set 같은 친구들은 Collection 프로토콜을 준수하기 때문에 Subscripts로 접근이 가능하다.

struct Contact {
    var planets: [String: String]
}

let contact = Contact(planets: [
    "지구": "Earth",
    "달": "Moon"
])

let earth = contact["지구"] // Error

Value of type 'Contact' has no subscripts (Contact에 Subscripts가 없다고 에러가 나온다)

struct Contact {
    var planets: [String: String]
    
    subscript(planet: String) -> String? {
        return self.planets[planet]
    }
}

let contact = Contact(planets: [
    "지구": "Earth",
    "달": "Moon"
])

let earth = contact["지구"] // Earth

subscript를 타입 내부에 구현해주면 된다.

struct Contact {
    var planets: [String: String]
    
    subscript(planet: String) -> String? {
        get {
            return self.planets[planet]
        }
        set {
            self.planets[planet] = newValue
        }
    }
}

var contact = Contact(planets: [
    "지구": "Earth",
    "달": "Moon"
])

var earth = contact["지구"] // Earth
contact["지구"] = "Mars"
let mars = contact["지구"] // "Mars"

이런식으로 subscript는 set연산도 가능하다.

2. dynamicMemberLookup

만약 dynamicMemberLookup을 사용하는 타입이 있다면 dynamicMemberLookup을 사용한다고 알려주어야 한다.

@dynamicMemberLookup //선언부 추가
struct Contact {
    var planets: [String: String]
    
    subscript(dynamicMember planet: String) -> String? { // dynamicMemberLookup 전용 메소드 추가
        return self.planets[planet]
    }
}

var contact = Contact(planets: [
    "지구": "Earth",
    "달": "Moon"
])

var earth = contact[dynamicMember: "지구"] // Earth

위의 Subscripts의 예시와 비슷하지만 dynamicMember라는 파라미터를 같이 쓰도록만 바뀌었다.

var contact = Contact(planets: [
    "지구": "Earth",
    "달": "Moon"
])

let earth = contact.지구 // Earth
let earth = contact.화성 // nil

이렇게 dot syntax를 사용할 수 있다.

없는 값 화성으로 부르면 nil이 나온다.

이처럼 Contact에 지구라는 프로퍼티는 없지만 dynamicMemberLookup이 Subscript를 dot syntax로 호출할 수 있도록 도와주는 것임

자료출처

https://zeddios.tistory.com/1224?category=685736