ios - 如何让 2 个泛型使用相同的 T 类型
问题描述
想象一下,我有一个具有以下类型的视图控制器工厂:
protocol ViewFactoryType {
associatedtype T
func create(for scene: T) -> UIViewController
}
final class ViewFactory<T>: ViewFactoryType {
func create(for scene: T) -> UIViewController {
return .init()
}
}
而且我还有一个具有以下类型的导航路由器:
protocol RouterType {
associatedtype T
func navigate(to target: T, using transition: Transition)
}
我想做的是创建一个实例RouterType
并传递它和一个ViewFactory
.
两种泛型T
类型实际上将使用相同的Scene
类型。
我尝试按如下方式创建该路由器:
final class AppRouter<T>: RouterType {
private let viewControllerFactory: ViewFactoryType
private let navigationController: UINavigationController
public init(navigationController: UINavigationController, viewControllerFactory: ViewFactoryType) {
self.navigationController = navigationController
self.viewControllerFactory = viewControllerFactory
}
public func navigate(to target: T, using transition: Transition) {
routeTo(viewControllerFactory.create(for: target), transition: transition)
}
private func routeTo(_ viewController: UIViewController, transition: Transition) {
switch transition {
case .push: navigationController.pushViewController(viewController, animated: true)
case .present: navigationController.present(viewController, animated: true)
case .replace: navigationController.setViewControllers([viewController], animated: false)
}
}
}
但是,这会产生错误:
Protocol 'ViewFactoryType' can only be used as a generic constraint because it has Self or associated type requirements
和
Member 'create' cannot be used on value of protocol type 'ViewFactoryType'; use a generic constraint instead
通过使用扩展,我能够稍微解决这个问题:
final class AppRouter<T> {
private let viewControllerFactory: ViewFactoryType
private let navigationController: UINavigationController
public init(navigationController: UINavigationController, viewControllerFactory: ViewFactoryType) {
self.navigationController = navigationController
self.viewControllerFactory = viewControllerFactory
}
private func routeTo(_ viewController: UIViewController, transition: Transition) {
switch transition {
case .push: navigationController.pushViewController(viewController, animated: true)
case .present: navigationController.present(viewController, animated: true)
case .replace: navigationController.setViewControllers([viewController], animated: false)
}
}
}
extension AppRouter: Router where T == Scene {
func route(to target: Scene, as transition: Transition) {
}
}
但是如果我也添加它,工厂方法没有正确的类型func route(to target: Scene, as transition: Transition)
解决方案
您不能associatedtype
以这种方式传递属性。编译器不了解它们应该如何关联或您期望它们如何使用。
您可以重构您AppRouter
以接受代表ViewFactoryType
它应该期望的类型。
final class AppRouter<T, R> {
private let viewControllerFactory: R
private let navigationController: UINavigationController
public init(navigationController: UINavigationController, viewControllerFactory: R) {
self.navigationController = navigationController
self.viewControllerFactory = viewControllerFactory
}
private func routeTo(_ viewController: UIViewController, transition: Transition) {
switch transition {
case .push: navigationController.pushViewController(viewController, animated: true)
case .present: navigationController.present(viewController, animated: true)
case .replace: navigationController.setViewControllers([viewController], animated: false)
}
}
}
extension AppRouter: RouterType where T == Scene, R == ViewFactory<T> {
func navigate(to target: Scene, as transition: Transition) {
let viewController = viewControllerFactory.create(for: target)
routeTo(viewController, transition: transition)
}
}
您现在可以通过传递正确的类型来创建实例
let viewControllerFactory = ViewFactory<Scene>()
let router = AppRouter<Scene, ViewFactory<Scene>>(navigationController: navigationController, viewControllerFactory: viewControllerFactory)
推荐阅读
- ios - 如何添加一个已经有父控制器的视图控制器作为另一个视图控制器的子控制器
- pdf-generation - 在客户端生成 PDF
- go - 带上下文取消的异步/等待模式
- javascript - 将 jest 测试套件生成为单独的文件而不是单个文件
- python - plotly:来自 ISO-3 代码的有效国家名称列表
- html - 在 power shell 中将 Splatted Array 转换为格式化的 HTML 电子邮件而不创建文件
- javascript - 在 Axios 中发出多个 Post 请求,然后获取所有响应以发出另一个请求
- reactjs - 使网格布局 div 具有相同的高度
- google-cloud-run - 如何确保仅在我的新云运行服务部署上提供流量?
- c# - 如何将迭代计数从主页带到剃刀中的嵌套局部视图