Swiftpack.co - Package - uias/Tabman

⭐️ Features

  • Easy to implement page view controller with interactive indicator bars.
  • Highly adaptable and powerful customization.
  • Fully extensible with mix-and-match component library.
  • Built on Pageboy, a simple, informative page view controller.
  • Automatically insets child view controller contents.

📋 Requirements

Tabman requires iOS 9 or above; and is compatibile with Swift 5.

📲 Installation

Swift Package Manager

Tabman is compatible with Swift Package Manager and can be integrated via Xcode.


Tabman is also available through CocoaPods:

pod 'Tabman', '~> 2.9'


Tabman is also available through Carthage:

github "uias/Tabman" ~> 2.9

🚀 Usage

The Basics

  1. Set up your view controller with the an array of view controllers that you want to appear.
  2. Set the PageboyViewControllerDataSource data source of the TabmanViewController.
  3. Create, customize and add as many TMBars as you want.
import Tabman
import Pageboy

class TabViewController: TabmanViewController {

    private var viewControllers = [UIViewController(), UIViewController()]

    override func viewDidLoad() {

        self.dataSource = self

        // Create bar
        let bar = TMBar.ButtonBar()
        bar.layout.transitionStyle = .snap // Customize

        // Add to view
        addBar(bar, dataSource: self, at: .top)

When adding a bar, you can choose to add it to the predefined areas (.top, .bottom, .navigationItem(item:)) or to a custom view with .custom(view:layout:). For more information, read the Adding a Bar guide.

  1. Configure your data sources.
extension TabViewController: PageboyViewControllerDataSource, TMBarDataSource {

    func numberOfViewControllers(in pageboyViewController: PageboyViewController) -> Int {
        return viewControllers.count

    func viewController(for pageboyViewController: PageboyViewController,
                        at index: PageboyViewController.PageIndex) -> UIViewController? {
        return viewControllers[index]

    func defaultPage(for pageboyViewController: PageboyViewController) -> PageboyViewController.Page? {
        return nil

    func barItem(for bar: TMBar, at index: Int) -> TMBarItemable {
        let title = "Page \(index)"
        return TMBarItem(title: title)

Bar Items

A bar will ask for a TMBarItemable for each page that is provided to the TabmanViewController dataSource. TMBarItemable is a protocol that can be used for custom item types, the default in Tabman being TMBarItem:

let item = TMBarItem()
item.title = "Item 1"
item.image = UIImage(named: "item.png")
item.badgeValue = "New"

UIKit Itemables

Tabman also provides support for some native UIKit types as TMBarItemable:

  • UINavigationItem
  • UITabBarItem

These types are unfortunately unable to support the dynamic updating of the bar when setting properties.

Choosing a look

Tabman provides numerous, easy to use template styles out of the box:

These are all available as types of TMBar in TMBar+Templates.

let bar = TMBar.ButtonBar()
let tabBar = TMBar.TabBar()


Bar customization is available via properties on each functional area of the bar. Each bar is made up of 4 distinct areas:


TMBarView is the root view of every bar, and provides the glue for meshing all the other functional areas together. You can change a few things here, such as background style and transitioning behavior.

bar.background.style = .blur(style: .extraLight)
bar.transitionStyle = .snap

This is also the entry point for all other customization.

🧲 Properties of Interest
  • backgroundView - TMBarBackgroundView which provides background styling.
  • scrollMode - What type of interactive scrolling to allow.
  • fadesContentEdges - Whether to fade the edges of the bar contents as it goes off-screen.

More: TMBarView Docs


TMBarLayout is the foundation of a TMBarView, dictating how bar buttons are displayed and laid out. Look here if you want to change things such as button spacing, content insets and other layout'y things.

bar.layout.contentInset = UIEdgeInsets(top: 0.0, left: 20.0, bottom: 0.0, right: 20.0)
🧲 Properties of Interest
  • contentMode - How the layout should display its contents; either restricted to the bar width with .fit or intrinsically sized with .intrinsic.
  • contentInset - Inset to be applied to the edges of the layout.
  • transitionStyle - How the layout should perform transition animations.
  • alignment - How the layout should be aligned in the bar.

More: TMBarLayout Docs


TMBarButton views are populated in the TMBarLayout and correspond to the items provided by the data source. This is the place to change things like fonts, image sizing and highlight colors.

As you will most likely dealing with more than one button, you can modify the whole set at once:

bar.buttons.customize { (button) in
	button.tintColor = .orange
	button.selectedTintColor = .red

This will be applied to both existing bar buttons and any that are added to the bar afterwards.

🧲 Properties of Interest
  • backgroundView - TMBarBackgroundView which provides background styling.
  • contentInset - Inset to be applied to the edges of the button.
  • transitionStyle (TMBarButtonCollection) - How the buttons should should perform transition animations.
  • badge - TMBadgeView that displays badgeValue from bar item.

More: TMBarButton Docs


Lastly is TMBarIndicator - which indicates the current page index status for the bar. You can change behavior characteristics here as well as how the indicator looks.

bar.indicator.overscrollBehavior = .compress
bar.indicator.weight = .heavy
🧲 Properties of Interest
  • overscrollBehavior - How the indicator should handle scrolling beyond the bounds of the bar items.
  • isProgressive - Whether the indicator should act progressively when transitioning through page indexes.
  • transitionStyle - How the indicator should should perform transition animations.

More: TMBarIndicator Docs

🎨 Advanced Customization

Tabman provides the complete freedom to mix-and-match the built-in components; and also define your own.

TMBarView leverages generics to define and serve the three distinct functional areas of the bar. This means...

// ...that the preset...
let bar = Bar.ButtonBar()

// ...is actually under the hood:
let bar = BarView<HorizontalBarLayout, LabelBarButton, LineBarIndicator>

So swapping in another type of layout, button or indicator could not be simpler.

Lets say you wanted to actually use a DotBarIndicator rather than the LineBarIndicator:

let bar = BarView<HorizontalBarLayout, LabelBarButton, DotBarIndicator>

The following components are available in Tabman:

Bar Layouts

  • TMHorizontalBarLayout - Layout that displays bar buttons sequentially along the horizontal axis.
  • TMConstrainedHorizontalBarLayout - Layout that displays bar buttons sequentially along the horizontal axis, but is constrained by the number of items it can display.

Bar Buttons

  • TMLabelBarButton - Button which contains a single text label.
  • TMTabItemBarButton - Button which mimics appearance of a UITabBarItem, containing a image and label vertically aligned.
  • TMBarButton.None - Display no visible bar buttons.

Bar Indicators

  • TMLineBarIndicator - Simple indicator that displays as a horizontal line.
  • TMChevronBarIndicator - Indicator that displays a vertical chevron centered along the X-axis.
  • TMBlockBarIndicator - Indicator that fills the bar, displaying a solid color.
  • TMDotBarIndicator - Indicator that displays a circular dot centered along the X-axis.
  • TMBarIndicator.None - Display no visible indicator.

Going Completely Custom

As replacing the type of layout, button or indicator is as easy as above; you have the ability to define your own subclasses without too much of a headache.

Custom Tabman Components

There are also example projects that showcase custom layouts and such:

  • Tinderbar - Tinder iOS app layout built with Tabman.

📐 Content Insetting

Tabman automatically adjusts any content in its child view controllers so that it displays correctly beneath any visible bars. It provides the following behaviors:

  • Updates contentInset and contentOffset appropriately for any UIScrollView or derived subclass found in the child view controller's subviews.
  • Sets additionalSafeAreaInsets to reflect the required safe areas including the bar contents. Any views constrained to the safe area in the child view controller will be laid out correctly (Only available in iOS 11 and above.)

TabmanViewController also provides barLayoutGuide, a UILayoutGuide that provides top and bottom anchors taking into account any bars added to the .top or .bottom TabmanViewController.BarLocation areas. The raw UIEdgeInsets are also available via .barInsets.

Auto insetting can be disabled by setting automaticallyAdjustsChildInsets to false - however this must be done before viewDidLoad.

Tabman will not provide any insetting behavior for bars that are added to custom views.

⚠️ Troubleshooting

If you are encountering issues with Tabman, please check out the Troubleshooting Guide.

If you're still having problems, feel free to raise an issue.

👨🏻‍💻 About

❤️ Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/uias/Tabman.

👮🏻‍♂️ License

The library is available as open source under the terms of the MIT License.


Stars: 1948


Used By

Total: 0


2.9.1 -


  • Crash when calling TMBarButton.allTargets due to TMBarButtonInteractionController not being hashable.

2.9.0 -


  • Dropped support for legacy Swift (4.x) versions.
  • Pageboy to 3.6.

Update Notes

This release drops support for Swift 4.x, meaning Tabman will now require Swift 5 going forwards. To use Tabman with a Swift 4 codebase, you must use Tabman 2.8.2 or older.

2.8.2 -


  • Layout issues when using Right-to-left languages via semanticContentAttribute.

2.8.1 -


  • Mixed language errors caused by Tabman.h header in Swift PM.

2.8.0 -

Improvements to TMLabelBarButton 🏷


  • verticalAlignment to TMLabelBarButton to allow for button contents to be vertically aligned.


  • Issue where TMLabelBarButton would fail to resize correctly when using custom fonts.

2.7.0 -

Improvements to layouts and insetting 🍺


  • centerDistributed to TMBarLayout.Alignment to center align all bar buttons.


  • Removed AutoInsetter as a dependency.
  • Child insetting logic now utilises additionalSafeAreaInsets only on iOS 11 and above.


  • #449 Infinite loop that could be caused by recursive layout calls.
  • #487 Issue where child contents could be requested to layout before being added to the view hierarchy.
  • #478 Issue where bar could fail to inset children when created dynamically for the page view controller.

2.6.3 -


2.6.2 -


  • Center aligned TMBarLayout not working for trailing buttons.
  • Center aligned TMBarLayout having an incorrect offset when using a non-zero contentInset.

2.6.1 -


  • Missing imports that could cause a Swift PM build to fail.

2.6.0 -

Improved iOS 13 support and more 📲


  • Support for Swift Package Manager in Xcode 11.
  • Support for Dark Mode in iOS 13.
  • contentInset to TMBadgeView allowing for custom badge content insets.


  • Issue where accessing safeAreaLayoutGuide could cause a crash on Jailbroken devices.
  • Issue where constraints in TMTabItemBarButton would not correctly be applied on iOS 13.
  • Issue where a TMSystemBar could fail to correctly extend background edges into system areas.

2.5.0 -

Support for vertical separators 🚀


  • Support for vertical separators between bar buttons to TMHorizontalBarLayout via showSeparators.
  • separatorColor to TMHorizontalBarLayout.
  • separatorInset to TMHorizontalBarLayout.
  • separatorWidth to TMHorizontalBarLayout.

2.4.3 -


  • Add support for multiple Swift versions to Podspec.

2.4.2 -


  • Incorrect Swift version in podspec, now 4.0.

2.4.1 -


  • Build issues with iOS 9.

2.4.0 -


  • #398 Ability to override automatic inset values via calculateRequiredInsets() on TabmanViewController.
  • #404 adjustsAlphaOnSelection to TMBarButton.
  • #338 Ability to hide / show the bar with TMHidingBar.
  • #403 Accessibility support to TMBarView.
  • #403 Accessibility support to TMBarItem.
  • #403 Accessibility support to TMBarButton.
  • #321 navigationItem(item:) to TabmanViewController.BarLocation with support for embedding a TMBar in a UINavigationBar.


  • Make TMBarItem open.
  • Make .title open on TMBarItem.
  • Make .image open on TMBarItem.
  • Make .badgeValue open on TMBarItem.
  • Make .items open on TMBarView.
  • Make .dataSource open on TMBarView.
  • Make .delegate open on TMBarView.
  • Make .scrollMode open on TMBarView.
  • Make .fadesContentEdges open on TMBarView.
  • Make .spacing open on TMBarView.
  • #396 Improved layout adaptability of TMTabItemBarButton on iPad and in landscape.
  • #404 TMBarButton no longer performs default fade transition in update(for selectionState:)

2.3.0 -


  • Added support for Swift 5.
  • Added support for Xcode 10.2.
  • Improved Swift 4 compatibility.

2.2.1 -


  • AutoInsetter to 1.6 - with numerous fixes and improvements for view controller insetting.

2.2.0 -

Support for Bar Button Badges 🔴


  • #363 .alignment property to TMBarLayout to adjust content alignment.
  • #378 .spacing property to TMBarView to adjust spacing between bar content / accessory views.
  • #373 setNeedsUpdate() to TMBarItemable to allow for dynamic item updates.
  • #387 Ability to show badges on TMBarButton via .badgeValue on TMBarItemable.
  • #392 tabmanParent to UIViewController.
  • #392 tabmanBarItems to UIViewController.


  • #378 Improved bar transitioning behavior when adjusting selected tab.
  • #373 .title is now mutable on TMBarItemable.
  • #373 .image is now mutable on TMBarItemable.

Upgrade Notes

There is unfortunately a breaking change in TMBarItemable for any conforming types by making .title, .image settable and introducing .badgeValue.

2.1.4 -


  • #383 Child insetting issues on iOS 10.

2.1.3 -


  • #366 Incorrect indicator positioning when using a Right-to-Left language.


  • #368 Improve access controls in TMBarIndicator and subclasses.
  • #368 Improve access controls in TMBarButton.
  • #368 Improve access controls in TMBarLayout.

2.1.2 -



  • Annoying conformance warning in TMBar caused by Swift compiler bug.

2.1.1 -


  • Make TMHorizontalBarLayout properties open.
  • Make TMConstrainedHorizontalBarLayout properties open.
  • Make TMLabelBarButton open.
  • Make TMTabItemBarButton open.


  • #358 Fix typo of TMBarDataSource in README.

2.1.0 -



  • #354 Remove UIViewController conformance to TMBarItemable.
  • Improved documentation.

Tabman 2 -

Redesigned + Rebuilt 🎉🍻


  • Redesigned and completely re-engineered bar layout system.
  • Support for dynamic page insertion & deletion via Pageboy 3.
  • Support for multiple bars, including dynamic addition and removal.
  • Simplified, more powerful customization via constrained types.
  • Ability to add accessory views to bars.
  • Support for UIKit components such as UINavigationItem to bar items.
  • Dramatically simplified creation and integration of custom components.


  • Improved animation & transitioning engine.
  • All views are now exposed via public API.


  • Numerous issues with automatic insetting of child contents.
  • A whole lot of performance fixes.
  • Numerous memory problems.

Upgrade Notes

This release and all v2.0 releases include API breaking changes from any previous 1.x release. When upgrading to v2.0 from a v1.x install, please read the accompanying migration notes that can be found here: Tabman 2 Migration Guide.

There is also now comprehensive documentation available at uias.github.io/Tabman

Tabman 2 - Beta 3 -

Upgrade Notes

This beta release and any following v2.0 releases will include API breaking changes from any previous 1.x release. When upgrading to v2.0 from a v1.x install, please read the accompanying migration notes that can be found here: Tabman 2 Migration Guide.

Tabman 2 - Beta 2 -

Upgrade Notes

This beta release and any following v2.0 releases will include API breaking changes from any previous 1.x release. When upgrading to v2.0 from a v1.x install, please read the accompanying migration notes that can be found here: Tabman 2 Migration Guide.

Tabman 2 - Beta 1 -

Upgrade Notes

This beta release and any following v2.0 releases will include API breaking changes from any previous 1.x release. When upgrading to v2.0 from a v1.x install, please read the accompanying migration notes that can be found here: Tabman 2 Migration Guide.

1.10.2 -


  • Cleaned up some potential memory issues in Bar reloading.

1.10.1 -


  • #331 App Store submission issues when integrating via Carthage.

1.10.0 -


  • Migrated to use Swift 4.2.