some View — what it is, opaque type in SwiftUI

Author: IT Sectr Published: 2026-06-24 Reading time: 8 min

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 — opaque type returned by the View protocol’s body property
  • Reverse generics — the concrete type is fixed by the compiler but hidden from calling code
  • Performance — some View adds no overhead unlike AnyView
  • Limitation — all return paths must have the same concrete type
  • @ViewBuilder solves the different types problem via ConditionalContent

What is some View in SwiftUI?

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.

Why is some View needed

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: How It Works

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.

swift
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.

Type Fixation and Stability

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.

swift
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.

some View vs AnyView: Comparison

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.

Criterionsome ViewAnyView
Resolution timecompile timeruntime
Performancedirect call, no overheadwrapping in existential container
Type flexibilitysingle concrete typeany View types
Dynamic switchingnot supportedsupported at runtime
Usage priorityalways when possibleonly when some View is impossible
PAT protocol supportyesyes

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.

some View and @ViewBuilder: Working Together

@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.

swift
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 Nesting

@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.

Practical Examples of some View

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.

swift
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.

swift
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.

swift
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

What does some View mean in SwiftUI?

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.

What is the difference between some View and AnyView?

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.

Why can’t some View be used with different types in if/else?

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.

How does some View affect SwiftUI performance?

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.

Can some View be used outside 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

  • some View — opaque Swift type returned by the body property of the View protocol
  • Opaque type — the reverse of generics: the implementation determines the type, hiding it from the caller
  • Compiler fixes the concrete type at compile time for code optimization
  • @ViewBuilder solves the different types problem via ConditionalContent
  • AnyView — type erasure with overhead, use only when some View is impossible
  • One-type rule — all some View return paths must have the same concrete type
  • some — a general Swift construct applicable to any protocols, not just View

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.

Discuss the project

Read also