some View vs any View — what is the difference, and why does SwiftUI use some?
Mental model. some is “I know exactly what this is, but it is none of your business.” any is “I genuinely do not know what is in the box.”
some View is an opaque type: one concrete type is chosen by the implementation and hidden from the caller. The compiler still knows it, so it can specialize and inline — and crucially, the view's identity and generic structure stay stable.
any View is an existential: the type is erased into an existential container with a value witness table and protocol witness tables. Calls go through witnesses, values may be boxed, and nothing can be specialized.
SwiftUI's body returns some View so the view graph is a concrete generic tree the framework can diff. You cannot even declare body as any View — an existential does not conform to View, so it cannot satisfy the requirement. The workaround, AnyView, conforms but erases identity and costs performance.
Common traps
- “
someis just prettierany.” They differ in dispatch, memory layout, and — most importantly — identity. Opaque types preserve the concrete type; existentials erase it. - “Two
some Viewbranches can be different types.” Anif/elsein a@ViewBuilderbecomes_ConditionalContent— the branches are wrapped, not unified into one opaque type.
They might follow up with
- Where is
any Viewactually correct? Storing a heterogeneous array of views, or a type-erasedAnyViewas a stored property when a generic parameter cannot be threaded through. - What is the runtime cost of
any? Possible heap boxing, indirect calls per method, no specialization, and larger value copies.
Related questions
- 1.4.6 What is an existential container? What is a witness table?
- 1.4.1 Generics vs protocols as types: when do you write <T: P>(T) vs any P?
- 1.4.3 What is the cost of any vs some on a hot path?
← Generics vs protocols as types: when do you write <T: P>(T) vs any P? What is the cost of any vs some on a hot path? →