SwiftUI: A custom reactive TabBar

Gerhard Schneider
The Startup
Published in
3 min readFeb 9, 2020
Photo by Russ Ward on Unsplash

Note 19-mar-2020: In the meantime, I went much deeper into the question how a scrollable tab view with animations can be realized using pure SwiftUI. I came up with a solution that is published on GitHub.

Please also note that there is a follow-up article on this one.

SwiftUI provides a TabView. However, checking for the currently selected tab, and reordering of the tabs lead to problems if you want, as an example, save and restore the new sort order on app restart.

So, I tried to design a TabBar which can be used pretty conveniently as replacement for the original TabView.

Wrapping the UITabBarController

First, we’re wrapping the UITabBarController into a UIViewControllerRepresentable. The procedure is explained in various tutorials across the web, so I’ll focus on some additional aspects here.

  1. This is the index that we want to have maintained by the UITabBarController .
  2. Similarily, this is the order in which the tabs shall appear.
  3. We set the Coordinator as delegate for the UITabBarController . This allows us to react on the events.
  4. From the given list of IRTabBarItems, we create the list of view controllers, as well as the attached UITabBarItems, that we need for the UITabBarController.
  5. If we have a tabOrder available, we sort those list of view controllers accordingly.
  6. We finish the setup of the tabBarController.

Reacting on events

Next, we need the Coordinator. Its job is simply to react on the events we’ll notice.

  1. We save the parent struct just for convenience. This avoids some castings lateron.
  2. We take the selectedIndex and save it to the parent’s @Published property.
  3. The same is true for the new sort order.

Defining the tab bar item

Now, let’s define an IRTabBarItem , so that we can provide title, image and target views to the tab bar.

Using the new view

We can now use the view like any other SwiftUI view:

  1. We use a model to provide all we need for the view. We’ll see that in a moment.
  2. That’s our new IRTabBar with the items provided by the model, and the selected index and the tab order bound to the model’s properties.

The model provides the convenience

Finally, we have to implement the model that the view observes.

  1. Those two are custom property wrappers that read and write values from/to the user defaults.
  2. These are the observed properties; if set, the user defaults are updated as well. (I’m sure this can be done nicer…)
  3. The preset for the tab bar items we want to present. Derived from an enumeration which provides title, systemImageName, view for each case.
  4. This reads the saved settings and sets the published properties accordingly.

Conclusion

With this view, your have a pretty easy way to add a reactive TabView to your app. If you need additional features, such as transitioning animations, you can easily add them to the Coordinator. Or, you can even publish the items and set them dynamically in. the model, e.g., if you want to show or hide tabs depending on other conditions.

--

--

Gerhard Schneider
The Startup

Helping humans and companies to evolve by opening new perspectives on the management of products and portfolios.