设计路由框架
问题
如何设计一个 iOS 路由框架?
答案
架构
核心实现
class Router {
static let shared = Router()
private var routes: [String: (RouteParams) -> UIViewController?] = [:]
private var interceptors: [RouteInterceptor] = []
// 注册
func register(_ pattern: String, handler: @escaping (RouteParams) -> UIViewController?) {
routes[pattern] = handler
}
// 跳转
func navigate(to url: String, from: UIViewController? = nil) {
guard let parsed = parse(url) else { return }
// 执行拦截器
for interceptor in interceptors {
if !interceptor.shouldProceed(route: parsed) {
interceptor.onIntercept(route: parsed, from: from)
return
}
}
guard let handler = routes[parsed.pattern],
let vc = handler(parsed.params) else { return }
let source = from ?? topViewController()
source?.navigationController?.pushViewController(vc, animated: true)
}
}
// 登录拦截器
struct LoginInterceptor: RouteInterceptor {
func shouldProceed(route: ParsedRoute) -> Bool {
if route.requiresAuth && !UserManager.shared.isLoggedIn {
return false
}
return true
}
func onIntercept(route: ParsedRoute, from: UIViewController?) {
Router.shared.navigate(to: "myapp://login", from: from)
}
}
注册方式
| 方式 | 说明 |
|---|---|
| 手动注册 | Router.register(...) |
| 自动注册(ObjC) | +load 中注册 |
| 注解 + 代码生成 | Swift Macro / SourceKit |
常见面试问题
Q1: 路由框架如何支持 SwiftUI?
答案:SwiftUI 使用 NavigationStack + NavigationPath,路由框架返回 AnyView 而非 UIViewController,或者通过枚举 Route 类型驱动导航。