Give your simulator superpowers

RocketSim: An Essential Developer Tool
as recommended by Apple

ContentUnavailableView: Handling Empty States in SwiftUI

ContentUnavailableView is a SwiftUI view introduced in iOS 17 during WWDC 2023. It allows you to handle cases of networking failure or empty search results. It’s essential to explain an empty state and its cause to your users.

While you can generate custom empty states, reusing standard SwiftUI components is convenient. Doing so will speed up your development process while you benefit from consistent and accessible UI simultaneously.

Making use of standard unavailable views

SwiftUI provides a set of ready-to-use unavailable views for common scenarios. For now, these only cover two different search empty states, but it could be possible more variants will follow in later releases.

Empty search states are common, and by reusing SwiftUI’s standard component, you’ll show a familiar view to your users with ease. For example, you might have a view to search in a list of articles:

struct ContentView: View {
    @ObservedObject private var viewModel = ArticlesViewModel()

    var body: some View {
        NavigationStack {
            List {
                ForEach(viewModel.searchResults) { article in
                    NavigationLink {
                        ArticleView(article)
                    } label: {
                        Text(article.title)
                    }
                }
            }
            .navigationTitle("Articles")
            .searchable(text: $viewModel.searchText)
            .overlay {
                if viewModel.searchResults.isEmpty, !viewModel.searchText.isEmpty {
                    /// In case there aren't any search results, we can
                    /// show the new content unavailable view.
                    ContentUnavailableView.search
                }
            }
        }
    }
}

If there aren’t any search results while the query is non-empty, we can show the new ContentUnavailableView. The outcome view looks as follows:

An example of the ContentUnavailableView using the standard search variant.
An example of the ContentUnavailableView using the standard search variant.

You can also use the search variant by providing the search query:

if viewModel.searchResults.isEmpty, !viewModel.searchText.isEmpty {
    /// In case there aren't any search results, we can
    /// show the new content unavailable view.
    ContentUnavailableView.search(text: viewModel.searchText)
}

Resulting in an empty state view that also shows the input query:

The ContentUnavailableView search variant shows the input query as a result.
The ContentUnavailableView search variant shows the input query as a result.

The resulting view looks familiar to your users since it’s widely used across the system. Another benefit is that the content unavailable view automatically translates into the languages your app supports. Note that it will only translate to languages your app supports so that you won’t have a single view being localized only.

Stay updated with the latest in SwiftUI

The 2nd largest newsletter in the Apple development community with 18,598 developers. Don't miss out – Join today:


Creating a custom ContentUnavailableView

While using the default provided variants is recommended, you can create custom unavailable views to match your design or handle different cases. You’ll have to manage localization and labels yourself, which results in more flexibility.

In our example, we’re going to provide a custom empty view that better matches our articles view:

ContentUnavailableView(
    "No Articles for \"\(viewModel.searchText)\"",
    systemImage: "doc.richtext.fill",
    description: Text("Try to search for another title.")
)

We’ve used a convenience initializer in this case, but we can write the same code using the more flexible initializer:

ContentUnavailableView {
    Label("No Articles for \"\(viewModel.searchText)\"", systemImage: "doc.richtext.fill")
} description: {
    Text("Try to search for another title.")
}

This initializer is excellent for extra flexibility, as you can use any view. Using the ContentUnavailableView this way results in the following output:

An example of a custom content unavailable view.
An example of a custom content unavailable view.

While we’ve primarily used the unavailable view to handle search results, you can also use it for other scenarios like network requests failures. The ContentUnavailableView provides convenience and allows you to match the system design with ease.

Conclusion

SwiftUI’s ContentUnavailableView allows you to provide feedback to users about the content being unavailable. You can use standard implementations like empty search results or create custom implementations. While custom implementations result in flexibility, standard variants have the benefit of being localized.

If you want to improve your SwiftUI knowledge, even more, check out the SwiftUI category page. Feel free to contact me or tweet me on Twitter if you have any additional tips or feedback.

Thanks!