Replace CYLTabBarController with native UITabBarController for main tabs.

Use a system scan tab slot with MainScanTabItem interception so scanner presentation no longer depends on CYL PlusButton, and remove the CYLTabBarController pod dependency.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-26 19:17:38 +08:00
parent 43179abf2c
commit 7469f92177
12 changed files with 217 additions and 208 deletions

View File

@ -3,26 +3,60 @@
// suixinkan
//
import CYLTabBarController
import UIKit
@MainActor
/// Tab 使 CYLTabBarController
final class MainTabBarController: CYLTabBarController {
/// Tab 使 TabBar
final class MainTabBarController: UITabBarController {
private let services: AppServices
private let badgeViewModel = MainTabBadgeViewModel()
private var tabNavigationControllers: [AppTab: TabNavigationController] = [:]
private var isSyncingTabSelection = false
///
var onScanTabSelected: (() -> Void)?
/// TabBar
private enum TabSlot: CaseIterable {
case home
case orders
case scan
case statistics
case profile
/// Tab
var appTab: AppTab? {
switch self {
case .home:
return .home
case .orders:
return .orders
case .scan:
return nil
case .statistics:
return .statistics
case .profile:
return .profile
}
}
/// Tab TabBar
static func index(for tab: AppTab) -> Int? {
allCases.firstIndex { $0.appTab == tab }
}
/// TabBar
static var scanIndex: Int? {
allCases.firstIndex(of: .scan)
}
}
///
init(services: AppServices) {
self.services = services
super.init(nibName: nil, bundle: nil)
MainScanPlusButton.onScanTap = { [weak self] in
self?.presentGlobalScanner()
}
// delegate = self
delegate = self
}
@available(*, unavailable)
@ -44,13 +78,6 @@ final class MainTabBarController: CYLTabBarController {
#endif
}
///
deinit {
Task { @MainActor in
MainScanPlusButton.onScanTap = nil
}
}
/// TabBar CustomMainTabBar
private func configureTabBarAppearance() {
tabBar.tintColor = AppDesign.primary
@ -76,26 +103,22 @@ final class MainTabBarController: CYLTabBarController {
tabBar.scrollEdgeAppearance = appearance
}
/// Tab CYLTabBarController Tab
/// Tab
private func configureTabs() {
let tabs = AppTab.allCases
tabBarItemsAttributes = tabs.map { makeTabBarItemAttributes(for: $0) }
viewControllers = tabs.map { tab in
let navigationController = TabNavigationController(tab: tab, services: services)
tabNavigationControllers[tab] = navigationController
return navigationController
tabNavigationControllers.removeAll()
viewControllers = TabSlot.allCases.map { slot in
if let tab = slot.appTab {
let navigationController = TabNavigationController(tab: tab, services: services)
navigationController.tabBarItem = tab.makeTabBarItem()
tabNavigationControllers[tab] = navigationController
return navigationController
}
let scannerPlaceholder = UIViewController()
scannerPlaceholder.tabBarItem = MainScanTabItem.makeTabBarItem()
return scannerPlaceholder
}
}
/// CYLTabBarController TabBarItem
private func makeTabBarItemAttributes(for tab: AppTab) -> [String: String] {
[
CYLTabBarItemTitle: tab.title,
CYLTabBarItemImage: tab.unselectedImageName,
CYLTabBarItemSelectedImage: tab.selectedImageName
]
}
/// ViewModel
private func bindBadgeViewModel() {
badgeViewModel.onChange = { [weak self] in
@ -132,6 +155,8 @@ final class MainTabBarController: CYLTabBarController {
/// TabBar
private func presentGlobalScanner() {
guard presentedViewController == nil else { return }
let scanner = OrderCodeScannerViewController()
scanner.onScanResult = { [weak self, weak scanner] result in
scanner?.dismiss(animated: true)
@ -147,9 +172,25 @@ final class MainTabBarController: CYLTabBarController {
navigationController.modalPresentationStyle = .fullScreen
present(navigationController, animated: true)
}
}
extension MainTabBarController: UITabBarControllerDelegate {
/// TabBar 使
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
guard viewControllers?.firstIndex(of: viewController) == TabSlot.scanIndex else {
return true
}
if let onScanTabSelected {
onScanTabSelected()
} else {
presentGlobalScanner()
}
return false
}
/// TabBar
override func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
guard !isSyncingTabSelection,
let navigationController = viewController as? TabNavigationController else { return }
@ -162,7 +203,7 @@ final class MainTabBarController: CYLTabBarController {
extension MainTabBarController: AppNavigationHost {
/// Tab
func selectTab(_ tab: AppTab) {
guard let index = AppTab.allCases.firstIndex(of: tab) else { return }
guard let index = TabSlot.index(for: tab) else { return }
guard selectedIndex != index else { return }
isSyncingTabSelection = true
selectedIndex = index