some View is a key Swift syntactic construct without which SwiftUI cannot work. According to Apple Swift Book, 2024, some View is an opaque type that hides the specific return type while maintaining strict typing at compile time. This construct allows the View protocol to have a unified body signature without revealing implementation details.
Key Takeaways
some View is an opaque type syntax introduced in Swift 5.1. It is used as the return type of the body property of the View protocol. The notation some View means: “the function or property returns some concrete type that conforms to the View protocol, but the calling code does not know and should not know which one.”
The concept of opaque type is the reverse side of generic programming. If generics allow the calling code to determine the type, then opaque type allows the implementation to determine the type, hiding it from the caller. This gives the developer the freedom to change the internal implementation without changing the contract.
According to Swift Evolution SE-0244, opaque types were added to support SwiftUI and the pattern of protocols with associated types (PAT), which cannot be used as a return type without this construct.
Without some View, the body signature would be impossible: the View protocol has an associated type Body that conforms to View. If body returned just View (as a protocol), Swift would not be able to work with protocols with Self requirements in the return position. some View solves this problem by providing a concrete but hidden type.
Opaque type is a special kind of type that behaves as concrete for the compiler but as abstract for the developer. When the compiler sees some View, it analyzes the implementation and determines the exact return type. This type is fixed and used for code generation without dynamic dispatch.
struct SimpleView: View {
var body: some View {
Text("Hello")
}
}
// Compiler sees: body -> Text, not some View
How it works: The Swift compiler infers the concrete type from the implementation. In the example above, the body contains only Text, so the compiler knows that body returns exactly Text, even though the signature is written as some View. This provides two optimizations: direct call without a virtual method table and the possibility of inlining.
If the body implementation changes (for example, instead of Text, a VStack of Text and Button is returned), the compiler redefines the concrete type. But for the calling code (SwiftUI), the signature remains the same — some View. This is the reverse side of generics: the calling code does not depend on implementation changes.
One of the key rules of opaque types: a function or property returning some View must always return the same concrete type. You cannot return Text in one if branch and Image in another. This limitation is checked by the compiler and serves as a guarantee for the calling code.
struct BadView: View {
var flag: Bool
var body: some View {
if flag {
Text("True") // Error: Text vs VStack
} else {
VStack {
Text("False")
Image(systemName: "xmark")
}
}
}
}
To solve this problem, @ViewBuilder is used, which wraps different branches into a ConditionalContent conditional container. The @ViewBuilder annotation over body is standard practice in SwiftUI, although it can be implicit if the body contains only a single expression.
AnyView is a type that erases the concrete View implementation (type erasure). It wraps any View into a single wrapper, allowing Views of different types to be stored in the same container. Unlike some View, AnyView works at runtime and adds overhead for wrapping and unwrapping.
| Criterion | some View | AnyView |
|---|---|---|
| Resolution time | compile time | runtime |
| Performance | direct call, no overhead | wrapping in existential container |
| Type flexibility | single concrete type | any View types |
| Dynamic switching | not supported | supported at runtime |
| Usage priority | always when possible | only when some View is impossible |
| PAT protocol support | yes | yes |
When to use AnyView: only in situations where some View is impossible due to the need for dynamic type switching at runtime. For example, when returning a View from a dictionary or in a recursive structure where the concrete type must change at each level. AnyView should be minimized, as each wrapping disables SwiftUI optimizations.
Common misconception: AnyView does not solve the problem of different types in body — @ViewBuilder solves that. AnyView erases the type but does not help the compiler infer a single type. Use @ViewBuilder for conditional logic and AnyView only for dynamic dispatch.
@ViewBuilder is a result builder designed specifically to work with some View. It allows using conditional logic (if/else, switch) and multiple expressions in the body while maintaining a single return type. ViewBuilder automatically wraps multiple expressions into TupleView and conditional branches into ConditionalContent.
struct ProfileView: View {
let user: User?
@ViewBuilder
var body: some View {
if let user {
UserCard(user: user)
Text("Online")
.font(.caption)
} else {
ProgressView("Loading...")
}
}
}
How it works: @ViewBuilder analyzes the code block and generates the appropriate buildBlock, buildOptional, or buildEither call. For conditional logic, ConditionalContent is created — a common type that hides the concrete types inside the branches but itself is a single type for the compiler. This solves the problem of different concrete types.
Without @ViewBuilder, a body property containing multiple expressions or conditional logic would cause a compilation error. This is why SwiftUI applies @ViewBuilder to body implicitly, and for custom properties and functions it must be added explicitly.
@ViewBuilder can be nested: one ViewBuilder inside another. This allows creating complex hierarchies with conditions at different levels. However, deep nesting complicates readability, so it is recommended to extract nested conditions into separate View components.
Example 1: returning a custom View from a computed property. A property can return some View, hiding the internal composition. This allows code reorganization without changing the public interface.
struct ArticleView: View {
var body: some View {
CardView {
HeaderView()
ContentView()
FooterView()
}
}
}
struct CardView<Content: View>: View {
let content: Content
var body: some View {
content
.padding(16)
.background(.white)
.cornerRadius(12)
.shadow(radius: 4)
}
}
Example 2: passing a View as a closure via @ViewBuilder. This pattern is used in standard SwiftUI containers (VStack, HStack, List) and can be implemented in custom components.
struct CustomContainer<Content: View>: View {
@ViewBuilder let content: () -> Content
var body: some View {
VStack(alignment: .leading) {
content()
}
.padding(20)
}
}
Example 3: a factory function returning some View. Allows creating Views depending on parameters without revealing the implementation. This is especially useful for libraries and reusable components.
func makeIcon(for status: Status) -> some View {
switch status {
case .success:
Image(systemName: "checkmark.circle.fill")
.foregroundColor(.green)
case .error:
Image(systemName: "xmark.circle.fill")
.foregroundColor(.red)
case .pending:
ProgressView()
}
}
Frequently Asked Questions
some View is an opaque type, meaning that some concrete type conforming to the View protocol is returned. The concrete type is fixed by the compiler but hidden from the calling code. This provides strict typing without revealing implementation details.
some View is resolved at compile time with zero overhead. AnyView uses type erasure at runtime with additional costs for wrapping in an existential container. Use some View whenever possible, AnyView only for dynamic type switching.
An opaque type requires a single concrete type for all return paths. if/else with different types violates this requirement. @ViewBuilder solves the problem by wrapping branches into ConditionalContent — a single type that hides the differences of concrete implementations.
some View does not reduce performance — the compiler knows the exact type and generates direct code. Conversely, any View (as a protocol) would require dynamic dispatch. some View is an optimization mechanism built into the design of SwiftUI.
Yes, some is a general Swift 5.1 construct not tied to SwiftUI. It can be used with any protocols: some Equatable, some Codable, some Collection. This is useful for hiding complex nested types such as [String: [Int]].
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also