The dynamic keyword and message dispatch
dispatch mechanisms and ObjC runtime.
dynamic forces Objective-C message dispatch via objc_msgSend, enabling KVO and swizzling, at the cost of skipping inlining and devirtualization.
WHAT THIS TESTS It probes whether you understand Swift's four dispatch styles and the precise role dynamic plays in Objective-C runtime features.
SWIFT DISPATCH BACKGROUND Swift uses inline or static dispatch for many calls, vtable dispatch for non-final class methods, witness-table dispatch for protocol requirements, and Objective-C message dispatch when needed. The compiler prefers the fastest option that preserves correctness, inlining and devirtualizing aggressively.
WHAT DYNAMIC DOES Marking a member dynamic forces it through the Objective-C messaging path, objc_msgSend, every time, even when the compiler could otherwise resolve it statically. Because objc_msgSend looks the selector up at runtime, the implementation can be replaced or intercepted, which is exactly what enables Key-Value Observing, which swizzles setters, and manual method swizzling. dynamic usually appears together with @objc, since the member must be visible to the Objective-C runtime; @objc alone exposes the member but does not by itself force dynamic dispatch in all cases.
PERFORMANCE TRADE-OFFS Message dispatch cannot be inlined or devirtualized and carries per-call lookup overhead. In a tight loop this is measurable. Static and inline dispatch let the optimizer fold and specialize code. So dynamic is a deliberate trade of speed for runtime flexibility, used sparingly.
COMMON WRONG ANSWERS Saying dynamic is just polymorphism or method overriding, which vtable dispatch already provides. Conflating dynamic with @objc; they are related but not identical. Claiming dynamic improves performance.
LIKELY FOLLOW-UPS How does KVO use dynamic? What is the difference between dynamic and final? When does Swift use witness tables? How does the optimizer devirtualize a non-final method?
ONE CONCRETE EXAMPLE You want KVO on a Swift property progress. You declare @objc dynamic var progress: Double. The dynamic attribute routes the setter through objc_msgSend so the KVO machinery can swizzle it and emit change notifications. If you drop dynamic, observers never fire because the call is dispatched statically and bypasses the runtime hook.
Read the original → docs.swift.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.