SwiftUI Navigation

Jun 20 2024 · Swift 5.9, iOS 17.0, Xcode 15.0

Lesson 03: TabView in SwiftUI

Demo

Episode complete

Play next episode

Next
Transcript

Setting Tab Badges

SwiftUI also lets you add a badge to each tab. This badge provides a way to share extra information with the user, but the available space limits the amount of data you can show. You’ll add a badge item to indicate the number of incoming and outgoing flights to the Flight Status and a short text badge showing the date to the central tab.

First, open FlightStatusBoard.swift and add the following code to the first tabItem just before the .tag(0) line:

.badge(shownFlights.filter { $0.direction == .arrival }.count)

The simplest badge displays a number on the tab icon. This number can represent anything you want. Here, you filter the list of flights to only those arriving and use the count property to get the number of flights. Add a similar line to the last tabItem before the .tag(2) line:

.badge(shownFlights.filter { $0.direction == .departure }.count)

Again, you use the same filter and get a count with the count property of the collection. In most cases, you’ll add a number indicator to a tab, but you can also add short text.

Add the following code to the top of the body after the shownFlights property:

var shortDateString: String {
  let dateF = DateFormatter()
  dateF.timeStyle = .none
  dateF.dateFormat = "MMM d"
  return dateF.string(from: Date())
}

This property returns a string with today’s month and date. You can then use this property as a badge. Add the following line after the second tabItem before the .tag(1) modifier:

.badge(shortDateString)

Now, run the app and tap the Flight Status option. You’ll see the new badges on each tab at the bottom of the view:

Paging Views

You’ve explored the most common tab view, which shows each tab as a separate space at the bottom of the view. SwiftUI also supports two other styles of tabs based on pages. Each tab takes the entire view in this style, with SwiftUI providing a minimal navigation indicator that floats over the content. You’ll now convert your tabs to this style to better understand their differences.

Open FlightStatusBoard.swift and add the following code before the .navigationTitle("Today's Flight Status") modifier:

.tabViewStyle(.page)

When you tap the Flight Status button, you’ll see a much different tab layout. The tab contents occupy the entire view. Your tab text, images, and badges no longer appear. In a page view, the user swipes between the pages instead of clicking a tab to activate each one. Right now, your user might not even realize there are multiple tabs.

SwiftUI does display a page index, but since the default colors are light, they vanish against a white background, such as the tabs in your view. To fix this problem, add the following code after the tabViewStyle(_:) modifier:

.indexViewStyle(.page(backgroundDisplayMode: .always))

This code tells SwiftUI to display a page index view over the contents of the view. The darker background ensures that the page index shows up over any content.

Tap Flight Status to see that while the text and badges still don’t show, the Image you applied to each tab shows as the icon of the page index. If you hadn’t used an image, the page index would show as a single circle for the tab.

This use of this navigation style is a matter of aesthetics. It provides more space for the content, but you may need to use some space to provide the information the tab title did in the traditional tab view. To clarify the contents of each page in the page style, you’ll put that information into the navigation title. Add the following code before the first tabItem (before the // 3):

.navigationTitle("Arrivals")

You learned in an earlier lesson that the navigationTitle(_:) modifier lets you apply a title from anywhere inside a navigation stack. Since this TabView exists inside a NavigationStack, you can use it to add a label for each tab that will apply to the NavigationStack.

Next, add the following code after FlightList(flights: shownFlights):

.navigationTitle("All Flights")

Last, add the following code before the final tabItem:

.navigationTitle("Departures")

Now, you’ll see the title in the navigation bar above the tabs. With the new titles, the contents of each view become clear. The page index also gives the user a visual indication that more tabs exist and where the current page lies within all the pages. You’ll also notice the page indicators built from images (the ascending and descending airplanes) differ from one created using an SF Symbol (All). Many of the rules of badge images, such as no rotation, still apply, but it becomes more challenging to resize images of different types consistently.

For apps that present parallel information, such as different cities in a weather app, you’ll find the page style of tab view a common way to present data. You’ll also see it used for wizard-type interfaces where each tab represents a step within an overall process. Use the page-style TabView in SwiftUI for onboarding screens on the first app launch, ensuring a user-friendly introduction that seamlessly introduces and showcases essential functionalities.

See forum comments
Cinema mode Download course materials from Github
Previous: TabView in SwiftUI Next: Conclusion