Logo for tanaschita.com

How to avoid using AnyView in SwiftUI

Boost SwiftUI performance by using AnyView alternatives.

02 Aug 2021 · 5 min read

SwiftUI provides the type-erased view AnyView that can be used as a wrapper for any other SwiftUI view, for example to be able to return multiple view types from a function.

While using AnyView might be a good choice in some cases, Apple recommends using alternatives when possible.

That’s because SwiftUI uses a so called structural identity mechanism, where SwiftUI uses the view's type to identify it and to determine when they should be updated. Since AnyView erases the type of the view, it reduces SwiftUI’s ability to efficiently update the views.

Using ViewBuilder instead of AnyView

Let's get to an example where we might be tempted to use AnyView.

When defining view properties or functions that return a view, we often use the some View opaque return type so we don't need to explicitly define the exact return type.

private var nameView: some View {
if isEditable {
return TextField("Your name", text: $name)
} else {
return Text(name)
}
}
Sponsorship logo
Preparing for a technical iOS job interview
Check out my new book on preparing for a technical iOS job interview with over 200 questions & answers. Test your knowledge on iOS topics such as Swift & Objective-C, SwiftUI & UIKit, Combine, HTTP Networking, Authentication, Core Data, Concurrency with async/await, Security, Automated Testing and more.
LEARN MORE

But the above code won't compile with the error message Function declares an opaque return type, but the return statements in its body do not have matching underlying types.

To resolve the error and return the same type for both views, we might be tempted to wrap them in AnyView.

private var nameView: some View {
if isEditable {
return AnyView(TextField("Your name", text: $name))
} else {
return AnyView(Text(name))
}
}

But there is a better solution to solve the compiler error - the ViewBuilder attribute.

The ViewBuilder attribute allows us to compose multiple views into a single return type.

@ViewBuilder
private var nameView: some View {
if isEditable {
TextField("Your name", text: $name)
} else {
Text(name)
}
}

All we have to do is to add the attribute to our property or function and remove the return statements.

That's the same mechanism the body of a SwiftUI view uses. The only difference is, that we explicitly have to add the ViewBuilder attribute on our own properties and functions.

Using Group instead of AnyView

By using the Group type, we can collect multiple views into a single one without affecting the layout of those views.

private var nameView: some View {
Group {
if isEditable {
TextField("Your name", text: $name)
} else {
Text(name)
}
}
}

Since Group uses ViewBuilder, we can group different kinds of views with conditional statements.

Using Generics instead of AnyView

Another common situation where we might be tempted to use AnyView is when we would like to store a view without knowing its type.

struct FlyoutView: View {
let headerView: AnyView
var body: some View {
VStack {
headerView
Spacer()
// other views
}
}
}

In the example above, we want the headerView to be of a flexible type. Since we can’t use the some View opaque return type for stored properties, AnyView seems like a good choice.

A more elegant and performant solution would be using generics.

struct FlyoutView<HeaderView> : View where HeaderView : View {
let headerView: HeaderView
var body: some View {
VStack {
headerView
Spacer()
}
}
}

When creating a FlyoutView, we don't need to wrap the header view in AnyView.

FlyoutView(headerView: Text("Header view"))

The same generics approach is used by many views provided by SwiftUI.

struct VStack<Content> : View where Content : View {
}

As we can see above, the content view of a VStack is of a generic type that conforms to View.

Conclusion

Using AnyView can be avoided in most situations. The explored alternatives did not only add more performance to our SwiftUI views, they also resulted in a more elegant readable code.

Sponsorship logo
Preparing for a technical iOS job interview
Check out my new book on preparing for a technical iOS job interview with over 200 questions & answers. Test your knowledge on iOS topics such as Swift & Objective-C, SwiftUI & UIKit, Combine, HTTP Networking, Authentication, Core Data, Concurrency with async/await, Security, Automated Testing and more.
LEARN MORE

Newsletter

Image of a reading marmot
Subscribe

Like to support my work?

Say hi

Related tags

Articles with related topics

swiftui

swift

ios

Understanding basic animations in SwiftUI

Learn different options to animate SwiftUI views.

16 Jan 2023 · 4 min read

Latest articles and tips

© 2023 tanaschita.com

Privacy policy

Impressum