Hotwire Native Ios Tab Bar Patterns

Hotwire Native iOS Tab Bar App — HotwireTabBarController Implementation and Debugging

Here are the problems encountered when switching from a single Navigator to the HotwireTabBarController pattern while wrapping a Rails app with Hotwire Native. Bugs that were invisible in the simulator surfaced on TestFlight, and local dev environment settings got tangled – multiple points where time was wasted. 1. HotwireTabBarController Basic Structure Instead of a single Navigator, each tab has its own independent Navigator and WKWebView. // AppTab.swift enum AppTab: String, CaseIterable { case home, ai, request var systemImage: String { switch self { case .home: return "house" case .ai: return "message" case .request: return "checkmark.circle" } } var selectedSystemImage: String { switch self { case .home: return "house.fill" case .ai: return "message.fill" case .request: return "checkmark.circle.fill" } } var url: URL { let base = AppDelegate.baseURL switch self { case .home: return base.appendingPathComponent("dashboard") case .ai: return base.appendingPathComponent("conversations") case .request: return base.appendingPathComponent("service_requests") } } var hotwireTab: HotwireTab { HotwireTab( title: "", image: UIImage(systemName: systemImage)!, selectedImage: UIImage(systemName: selectedSystemImage)!, url: url ) } } // SceneController.swift core part private lazy var tabBarController: HotwireTabBarController = { let controller = HotwireTabBarController(navigatorDelegate: self) controller.load(AppTab.allCases.map(\.hotwireTab)) // Show only tab icons, remove text controller.viewControllers?.forEach { vc in vc.tabBarItem.title = nil vc.tabBarItem.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0) (vc as? UINavigationController)?.delegate = self } return controller }() To remove tab titles and keep only icons, both tabBarItem.title = nil and imageInsets adjustment are needed. Setting only title to nil leaves the icon position unchanged, looking awkward. ...

2025-12-26 · 6 min read · Seunghan
Privacy Policy Terms Disclaimer Contact