SwipeMenuViewController provides SwipeMenuView and SwipeMenuViewController, which make it easy to build swipe-based paging UI. A scrollable tab bar sits above a horizontally paging content area, and swiping the content keeps the tab selection in sync. The interface is modeled on UIKit's own data source and delegate patterns, so it should feel familiar.
Here are some of the styles you can build with SwipeMenuView.
| Segmented Tab & Underline | Flexible Tab & Underline | Flexible Tab & Circle |
|---|---|---|
![]() |
![]() |
![]() |
- iOS 16.0+
- Xcode 26.0+ / Swift 6.2+
Need an older toolchain or deployment target? Use the 4.x releases.
SwipeMenuViewController is distributed exclusively through Swift Package Manager.
In Xcode, choose File ▸ Add Package Dependencies… and enter:
https://github.com/yysskk/SwipeMenuViewController.git
Or add it to a Package.swift manifest:
dependencies: [
.package(url: "https://github.com/yysskk/SwipeMenuViewController.git", .upToNextMajor(from: "5.0.0"))
]The quickest way to get started is to subclass SwipeMenuViewController and add your pages as child view controllers:
import SwipeMenuViewController
final class MenuViewController: SwipeMenuViewController {
override func viewDidLoad() {
pages.forEach { addChild($0) }
super.viewDidLoad()
}
private let pages: [UIViewController] = {
let first = UIViewController()
first.title = "First"
let second = UIViewController()
second.title = "Second"
return [first, second]
}()
}By default each page is backed by one of the controller's children: the page count is children.count, each tab title is the child's title, and each page shows the child's view. Override the SwipeMenuViewDataSource methods for fully custom paging.
To place the paging UI inside a view hierarchy you already have, add a SwipeMenuView directly, set its dataSource (and optional delegate), and customize it with SwipeMenuViewOptions.
SwipeMenuView is a plain UIView, so it only reads each page's view — it cannot establish view-controller containment for you. When your pages are view controllers, add them as children yourself so they receive the usual appearance and trait-collection callbacks:
import SwipeMenuViewController
final class CatalogViewController: UIViewController {
private let swipeMenuView = SwipeMenuView(frame: .zero)
private let pages: [UIViewController] = ["Sports", "News", "Weather"].map { title in
let page = UIViewController()
page.title = title
return page
}
override func viewDidLoad() {
super.viewDidLoad()
// Establish containment: the host view controller owns the pages.
pages.forEach { addChild($0) }
swipeMenuView.frame = view.bounds
swipeMenuView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
swipeMenuView.dataSource = self
view.addSubview(swipeMenuView)
var options = SwipeMenuViewOptions()
options.tabView.style = .segmented
swipeMenuView.reloadData(options: options)
// reloadData added each page's view, so finish containment.
pages.forEach { $0.didMove(toParent: self) }
}
}
extension CatalogViewController: SwipeMenuViewDataSource {
func numberOfPages(in swipeMenuView: SwipeMenuView) -> Int { pages.count }
func swipeMenuView(_ swipeMenuView: SwipeMenuView, titleForPageAt index: Int) -> String {
pages[index].title ?? ""
}
func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewControllerForPageAt index: Int) -> UIViewController {
pages[index]
}
}The delegate and data source callbacks are main-actor isolated, so implement them from your (main-actor) view controllers as usual. See the documentation for every SwipeMenuViewOptions field.
The full API reference and articles are published online with DocC:
Start with the Getting Started and Customizing Appearance articles for the full setup walkthrough and every available option. You can also build the documentation locally in Xcode with Product ▸ Build Documentation.
Bug reports and pull requests are welcome. Please open an issue using one of the templates, and make sure the test suite passes (xcodebuild test -scheme SwipeMenuViewController -destination 'platform=iOS Simulator,name=iPhone 16').
See CHANGELOG.md for the release history.
SwipeMenuViewController is available under the MIT license. See the LICENSE file for details.


