跳到主要内容

组件化路由

问题

iOS 组件化中主流的路由方案有哪些?各有什么优缺点?

答案

三种主流方案

1. URL Router(类似蘑菇街)

// 注册
Router.register("myapp://user/profile") { params -> UIViewController in
let userId = params["id"] as? String ?? ""
return UserProfileVC(userId: userId)
}

// 跳转
Router.open("myapp://user/profile?id=123")
  • ✅ 支持 Deep Link、跨端统一
  • ❌ 无编译检查,参数传递靠字符串

2. Protocol Router(类似 BeeHive)

// 定义协议(放在公共模块)
protocol UserServiceProtocol {
func showProfile(userId: String, from: UIViewController)
}

// 实现(在 User 模块内部)
class UserServiceImpl: UserServiceProtocol {
func showProfile(userId: String, from: UIViewController) {
let vc = UserProfileVC(userId: userId)
from.navigationController?.pushViewController(vc, animated: true)
}
}

// 注册
ServiceRouter.register(UserServiceProtocol.self, impl: UserServiceImpl())

// 调用方
let service = ServiceRouter.resolve(UserServiceProtocol.self)
service?.showProfile(userId: "123", from: self)
  • ✅ 类型安全,编译期检查
  • ❌ 每个模块需要暴露协议到公共层

3. Target-Action(CTMediator 思路)

// 中间人调用,利用 ObjC Runtime
class CTMediator {
func performTarget(_ name: String, action: String, params: [String: Any]) -> Any? {
let cls = NSClassFromString("Target_\(name)") as? NSObject.Type
let target = cls?.init()
let sel = NSSelectorFromString("Action_\(action):")
return target?.perform(sel, with: params)?.takeUnretainedValue()
}
}
  • ✅ 无需注册,利用 Runtime
  • ❌ 字符串硬编码,仅支持 ObjC

方案对比

方案类型安全Deep Link学习成本适合场景
URL RouterH5 交互多、需要 Deep Link
Protocol Router❌(需桥接)纯 Native、注重类型安全
Target-ActionObjC 项目
实际项目推荐

混合使用:Protocol Router 用于模块间 Swift 调用,URL Router 用于 Deep Link / Push 通知跳转。


常见面试问题

Q1: 如何处理模块间页面跳转?

答案:通过路由层解耦。模块 A 不直接 import 模块 B,而是通过注册的路由(URL 或 Protocol)间接获取目标 VC,消除编译依赖。

答案:Deep Link 是外部唤起 App 并导航到特定页面的机制(Universal Links / URL Scheme)。路由是 App 内部的页面跳转机制。通常让 Deep Link 解析后调用内部路由完成跳转,保持跳转逻辑统一。

相关链接