Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The @dynamicMemberLookup attribute instructs the Swift compiler to invoke a custom subscript method when a property is accessed that is not explicitly declared on the type. It bridges static type checking with dynamic runtime behavior by translating arbitrary dot-syntax property accesses into subscript calls. To satisfy the attribute’s requirements, the annotated type (class, struct, enum, or protocol) must implement at least one subscript(dynamicMember:) method. The compiler intercepts unresolved property accesses and rewrites them to pass the property identifier as the argument to this subscript. Swift supports two distinct mechanisms for dynamic member lookup: String-based and KeyPath-based.

String-Based Lookup

In String-based lookup, the compiler passes the name of the accessed property as a string literal. This approach bypasses compile-time property validation, deferring resolution entirely to runtime. The parameter accepted by the subscript must be String or a type that conforms to the ExpressibleByStringLiteral protocol. Syntax:
@dynamicMemberLookup
struct DynamicStringWrapper {
    // The parameter must be named 'dynamicMember' and accept a String 
    // or a type conforming to ExpressibleByStringLiteral
    subscript(dynamicMember member: String) -> Any {
        // Implementation logic to resolve the string identifier
        return "Resolved \(member)"
    }
}
Compiler Translation: When the compiler encounters an access to an undeclared property, it rewrites the AST (Abstract Syntax Tree) node:
let wrapper = DynamicStringWrapper()

// Developer writes:
let value = wrapper.arbitraryProperty

// Compiler translates to:
let value = wrapper[dynamicMember: "arbitraryProperty"]

KeyPath-Based Lookup

KeyPath-based lookup allows a type to dynamically expose the properties of another type while maintaining strict compile-time type safety. Instead of passing a string, the compiler passes a KeyPath (or WritableKeyPath, ReferenceWritableKeyPath) pointing to a property on a wrapped or associated type. Syntax:
@dynamicMemberLookup
struct DynamicKeyPathWrapper<WrappedType> {
    private var wrapped: WrappedType
    
    // The parameter must be named 'dynamicMember' and accept a KeyPath
    subscript<T>(dynamicMember keyPath: KeyPath<WrappedType, T>) -> T {
        get {
            return wrapped[keyPath: keyPath]
        }
    }
    
    // For value types (structs), modifying a stored property via a WritableKeyPath 
    // requires the subscript to be explicitly marked with the `mutating` keyword.
    mutating subscript<T>(dynamicMember keyPath: WritableKeyPath<WrappedType, T>) -> T {
        get { wrapped[keyPath: keyPath] }
        set { wrapped[keyPath: keyPath] = newValue }
    }
}
Compiler Translation: The compiler verifies that the accessed property exists on the WrappedType and enforces the correct return type T.
struct CoreData {
    var id: Int
}

// Declared as a variable to allow mutation via the WritableKeyPath subscript
var wrapper = DynamicKeyPathWrapper(wrapped: CoreData(id: 42))

// Developer writes:
let id = wrapper.id // Type inferred as Int
wrapper.id = 100    // Mutates the underlying wrapped property

// Compiler translates to:
let id = wrapper[dynamicMember: \CoreData.id]
wrapper[dynamicMember: \CoreData.id] = 100

Overloading and Resolution Rules

You can overload the subscript(dynamicMember:) method within the same type. The Swift compiler resolves the appropriate subscript using standard overload resolution rules based on:
  1. Argument Type: Whether the lookup can be satisfied by a KeyPath or requires falling back to a String (or ExpressibleByStringLiteral type).
  2. Return Type: If multiple String-based subscripts exist returning different types, the compiler infers the correct subscript based on the type context of the assignment.
  3. Mutability: The compiler will select a WritableKeyPath subscript over a read-only KeyPath subscript if the property access is a mutation (e.g., the left-hand side of an assignment).
Master Swift with Deep Grasping Methodology!Learn More