Integrate高德 SDK with simulator-safe build flags, add map views for operating area and punch points, refactor main tabs and key feature screens to UIKit with Diffable lists, and document Swift concurrency defaults in AGENTS.md. Co-authored-by: Cursor <cursoragent@cursor.com>
108 lines
3.7 KiB
Swift
108 lines
3.7 KiB
Swift
//
|
||
// TabNavigationController.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import UIKit
|
||
|
||
@MainActor
|
||
/// 单个 Tab 的导航栈,与 `AppRouter` 路径同步并在 push 时隐藏底部 TabBar。
|
||
final class TabNavigationController: UINavigationController, UINavigationControllerDelegate {
|
||
|
||
let appTab: AppTab
|
||
private let services: AppServices
|
||
private var isSyncingStack = false
|
||
|
||
/// 初始化实例。
|
||
init(tab: AppTab, services: AppServices) {
|
||
self.appTab = tab
|
||
self.services = services
|
||
super.init(nibName: nil, bundle: nil)
|
||
delegate = self
|
||
navigationBar.prefersLargeTitles = false
|
||
setViewControllers([tab.makeRootViewController(services: services)], animated: false)
|
||
registerNavigationBridge()
|
||
services.appRouter.router(for: appTab).onChange = { [weak self] in
|
||
self?.syncFromRouterPath()
|
||
}
|
||
}
|
||
|
||
@available(*, unavailable)
|
||
required init?(coder: NSCoder) {
|
||
fatalError("init(coder:) has not been implemented")
|
||
}
|
||
|
||
/// Push 指定应用路由,并同步写入 RouterPath。
|
||
func pushRoute(_ route: AppRoute, animated: Bool = true) {
|
||
let viewController = AppRouteViewControllerFactory.makeViewController(for: route, services: services)
|
||
viewController.hidesBottomBarWhenPushed = route.hidesTabBarWhenPushed
|
||
isSyncingStack = true
|
||
services.appRouter.router(for: appTab).navigate(to: route)
|
||
isSyncingStack = false
|
||
pushViewController(viewController, animated: animated)
|
||
}
|
||
|
||
/// navigationController相关逻辑。
|
||
func navigationController(
|
||
_ navigationController: UINavigationController,
|
||
didShow viewController: UIViewController,
|
||
animated: Bool
|
||
) {
|
||
syncRouterPathFromStack()
|
||
}
|
||
|
||
/// 注册NavigationBridge。
|
||
private func registerNavigationBridge() {
|
||
switch appTab {
|
||
case .home:
|
||
UIKitAppNavigation.homeNavigationController = self
|
||
case .profile:
|
||
UIKitAppNavigation.profileNavigationController = self
|
||
default:
|
||
break
|
||
}
|
||
}
|
||
|
||
/// 同步FromRouterPath状态。
|
||
private func syncFromRouterPath() {
|
||
guard !isSyncingStack else { return }
|
||
|
||
let routerPath = services.appRouter.router(for: appTab)
|
||
let targetDepth = routerPath.path.count
|
||
let currentDepth = max(viewControllers.count - 1, 0)
|
||
|
||
if targetDepth > currentDepth {
|
||
// Router 路径变深:按路径依次 push 缺失页面
|
||
for index in currentDepth..<targetDepth {
|
||
let route = routerPath.path[index]
|
||
let viewController = AppRouteViewControllerFactory.makeViewController(for: route, services: services)
|
||
viewController.hidesBottomBarWhenPushed = route.hidesTabBarWhenPushed
|
||
pushViewController(viewController, animated: true)
|
||
}
|
||
return
|
||
}
|
||
|
||
if targetDepth < currentDepth {
|
||
// Router 路径变浅:pop 至目标深度
|
||
if targetDepth == 0 {
|
||
popToRootViewController(animated: true)
|
||
} else if targetDepth < viewControllers.count {
|
||
popToViewController(viewControllers[targetDepth], animated: true)
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 同步RouterPathFromStack状态。
|
||
private func syncRouterPathFromStack() {
|
||
guard !isSyncingStack else { return }
|
||
|
||
let routerPath = services.appRouter.router(for: appTab)
|
||
let depth = max(viewControllers.count - 1, 0)
|
||
if depth < routerPath.path.count {
|
||
isSyncingStack = true
|
||
routerPath.path = Array(routerPath.path.prefix(depth))
|
||
isSyncingStack = false
|
||
}
|
||
}
|
||
}
|