When would you use Any or AnyObject, and why should they be avoided?
What they actually are
Any— can hold a value of literally any type: structs, enums, classes, functions, closures, tuples, optionals.AnyObject— can hold any instance of a class type.
Under the hood, Any is essentially the most general existential container — same witness-table/boxing machinery, but with no protocol conformance requirements. For values larger than the inline buffer (3 words), it heap-allocates a box. AnyObject is cheaper since class instances are already just a pointer.
Legitimate uses
- Heterogeneous collections where you genuinely don’t know the types in advance — e.g., parsing JSON before you’ve modeled it.
- Objective-C interop boundaries — bridging to
NSObject-based APIs, KVO,@objcprotocols. - Truly generic infrastructure code — a low-level cache, logger, or dependency container storing arbitrary values by key.
Why they should be avoided otherwise
- You lose compile-time safety entirely — every extraction needs
as?/as!, pushing failures from compile time to runtime. - Performance cost — heap boxing for anything larger than 24 bytes, plus dynamic type-checking overhead on every cast.
- They erase exactly the information generics/opaque types exist to preserve.
- They spread untyped code outward — once a value enters as
Any, the “know what this actually is” burden shifts to runtime logic.
The decision rule
Ask: do I actually not know the type, or do I just not want to write the generic constraint? Prefer, in order of increasing flexibility/cost: concrete type → generic constraint → some Protocol → any Protocol → Any/AnyObject only as a last resort.
One-liner if pressed: “Any/AnyObject are appropriate at genuine type-erasure boundaries — JSON parsing, Objective-C interop, plugin systems — but everywhere else they trade away compile-time safety and add real boxing/dispatch overhead for a problem generics or existential protocols already solve more precisely.”