AnyView is a type-erased wrapper used to store views of different types in a single variable, property, or array. Since SwiftUI uses specific view types (e.g., Text, Image, Button), it can sometimes be difficult to work with views dynamically, especially if you need to return different view types conditionally. AnyView provides a way around this by erasing the specific view type.
Why Use AnyView?
- Conditional Views: If you need to return different view types based on conditions,
AnyViewcan wrap each view, so they can all conform to the same expected type. - Collections of Mixed Views: When creating an array of views of different types,
AnyViewallows you to store them in a single array. - Dynamic Views: When views need to be determined at runtime or changed dynamically,
AnyViewprovides the flexibility to handle various types.
Basic Example of AnyView
import SwiftUI
struct ContentView: View {
@State private var isTextView = true
var body: some View {
VStack {
toggleableView()
.frame(width: 100, height: 100)
Button("Toggle View") {
isTextView.toggle()
}
}
}
@ViewBuilder
func toggleableView() -> some View {
if isTextView {
AnyView(Text("This is a Text View"))
} else {
AnyView(Image(systemName: "star"))
}
}
}
In this example:
- Conditionally Switching Views:
toggleableView()returns either aTextor anImagewrapped inAnyViewbased on theisTextViewstate. - Button to Toggle View: Each tap on “Toggle View” switches between showing a text view and an image.
Storing Mixed Views in an Array
AnyView is especially useful for arrays, where each element needs to be the same type.
import SwiftUI
struct ContentView: View {
var views: [AnyView] = [
AnyView(Text("Hello, SwiftUI!")),
AnyView(Image(systemName: "star")),
AnyView(Circle().fill(Color.blue).frame(width: 50, height: 50))
]
var body: some View {
VStack {
ForEach(0..<views.count) { index in
views[index]
}
}
}
}
Here:
- Array of AnyView: Different view types (
Text,Image,Circle) are stored in anAnyViewarray. - Displaying Each View:
ForEachiterates over the array, displaying each view in aVStack.
Using AnyView in Complex Conditionals
Consider a more complex UI where different conditions may yield different views. AnyView can help you handle these situations in a simplified way.
import SwiftUI
struct ContentView: View {
@State private var isLoggedIn = true
@State private var isAdmin = false
var body: some View {
VStack {
contentView()
.padding()
Button("Toggle User Role") {
isAdmin.toggle()
}
Button("Toggle Login Status") {
isLoggedIn.toggle()
}
}
}
func contentView() -> AnyView {
if isLoggedIn {
if isAdmin {
return AnyView(Text("Admin Dashboard"))
} else {
return AnyView(Text("User Dashboard"))
}
} else {
return AnyView(Text("Please Log In"))
}
}
}

In this example:
- Multiple Conditions:
contentView()returns different text based onisLoggedInandisAdmin. - Button to Toggle States: Each button changes the conditions, demonstrating how
AnyViewaccommodates complex logic.
Downsides of AnyView
While AnyView is flexible, it does come with some trade-offs:
- Performance: Wrapping views in
AnyViewincurs a slight performance overhead, as SwiftUI has to work harder to manage the type-erased views. This isn’t usually noticeable in small cases but can affect performance in more extensive hierarchies or frequently changing views. - Reduced Type Safety: Swift’s type system helps prevent certain kinds of errors. Using
AnyViewbypasses that system, which can make debugging more challenging.
Alternative: @ViewBuilder
In some cases, you might be able to avoid AnyView by using @ViewBuilder, which allows SwiftUI to handle multiple views in conditionals without type erasure.
import SwiftUI
struct ContentView: View {
@State private var isTextView = true
var body: some View {
VStack {
toggleableView()
.frame(width: 100, height: 100)
Button("Toggle View") {
isTextView.toggle()
}
}
}
@ViewBuilder
func toggleableView() -> some View {
if isTextView {
Text("This is a Text View")
} else {
Image(systemName: "star")
}
}
}
In this example:
- Using
@ViewBuilderlets SwiftUI handle different view types without wrapping them inAnyView, preserving type safety and potentially improving performance.
AnyViewenables the use of multiple view types in a single variable, property, or array.- It’s ideal for conditionally rendering different views and creating collections of varied view types.
- However,
@ViewBuilderis often a good alternative toAnyView, especially in conditional view code, due to better performance and type safety.