@dynamicMemberLookup is a Swift annotation that allows you to override access to an object's properties at runtime via subscript. Historically, this mechanism was introduced for more transparent integration with dynamic languages like Python, and it is aimed at more flexible data access routing in proxy objects, dynamic models, and DSLs.
Problem: Standard Swift requires properties to be explicitly declared and checks their existence at compile time. However, sometimes it is necessary to access properties by their names, which do not exist at compile time, such as when dealing with JSON, APIs, proxy objects, and script wrappers.
Solution: Use @dynamicMemberLookup and implement subscript(dynamicMember:) to intercept access attempts to non-existent properties.
Code example:
@dynamicMemberLookup struct JSON { private var data: [String: Any] subscript(dynamicMember member: String) -> Any? { data[member] } } let user = JSON(data: ["name": "Anna", "age": 23]) print(user.name as? String) // Anna
Key features:
Can dynamicMemberLookup be implemented for classes, or only for structs?
Yes, it can be applied to classes, structs, and enums (starting from Swift 5+). It is important to implement the corresponding subscript.
What happens if you access a non-existent property through dynamicMemberLookup?
It returns a value from the subscript; the responsibility for handling the absence of a value lies with your implementation.
For example, in the above example, if you access user.secret, nil will be returned.
Can dynamic access be done using keys of another type, such as Int?
Yes! You can declare subscript(dynamicMember:) with different argument labels and combine it with regular subscripts.
@dynamicMemberLookup struct ArrayProxy { private let array: [Int] subscript(dynamicMember member: String) -> Int? { if member == "first" { return array.first } if member == "last" { return array.last } return nil } subscript(index: Int) -> Int? { array[safe: index] } }
A developer uses @dynamicMemberLookup for a regular user model (User) to access any fields via strings. The code becomes opaque, and the IDE lost hints.
Pros:
Cons:
@dynamicMemberLookup is applied for working with arbitrary JSON objects whose fields are unknown in advance. The mechanism allows for elegant and safe (through Any?/optional binding) handling of unstructured data.
Pros:
Cons: