我正在尝试使用通用参数将通用数据注入视图控制器
T
。我有一个协议 Coordinator
,它声明了关联的类型 T 和类型为 data
的 T
变量。我的AppCoordinator
采用Coordinator
协议,并将T
的类型声明为String
。在我的 AppCoordinator
类中,我尝试使用通用参数 T
在视图控制器上设置数据。
我的想法是,类
WelcomeViewController
在实现Navigable协议时,为AppData
采用了data
的具体类型,所以我应该能够在AppCoordinator中设置数据的类型,即String这种情况下,也可以在视图控制器上进行设置。不知何故,我认为为了使其工作,协调器协议中的类型 T 必须与可导航协议中的类型 T 匹配,但是当我尝试通过在协调器协议中设置 associated type T: Navigable.T
来做到这一点时,例如,我收到此错误:“无法从‘Navigable’访问关联类型‘T’;请改用具体类型或通用参数库”。
我已阅读如何将依赖项注入 iOS 视图控制器?,以及以下部分:泛型解决的问题、泛型函数、类型参数、命名类型参数、类型约束、关联类型、泛型Where 子句、关联类型带有通用Where子句,来自Generics。
我该如何解决这个问题?
protocol Coordinator<T> {
associatedtype T
var navigationController: UINavigationController { get }
var data: T? { get }
func start<T>(data: T?, viewController: any Navigable)
}
class AppCoordinator: Coordinator {
typealias T = String
var data: T?
init(data: T? = nil, navigationController: UINavigationController) {
self.data = data
self.navigationController = navigationController
}
var navigationController: UINavigationController
func start<T>(data: T?, viewController: any Navigable) {
var viewController = viewController
viewController.data = data
}
}
protocol Navigable<T> where T == AppData {
associatedtype T
var data: T? { get set }
}
enum AppData {
case coordinatorData
}
class WelcomeViewController: UIViewController, Navigable {
var data: AppData?
var appCoordinator: (any Coordinator)?
typealias T = AppData
override func viewDidLoad() {
setUp()
}
}
您可以向
start
函数添加通用约束来实现您的目标:
protocol Coordinator<T> {
associatedtype T
var navigationController: UINavigationController { get }
var data: T? { get }
func start<U: Navigable>(data: T?, viewController: U) where U.T == T //<- constraint here
}
class AppCoordinator: Coordinator {
typealias T = AppData
typealias U = WelcomeViewController
var data: AppData?
init(data: T? = nil, navigationController: UINavigationController) {
self.data = data
self.navigationController = navigationController
}
var navigationController: UINavigationController
func start<U>(data: AppData?, viewController: U) where U : Navigable, AppData == U.T {
var viewController = viewController
viewController.data = data
}
}
protocol Navigable {
associatedtype T
var data: T? { get set }
}
enum AppData {
case coordinatorData
}
class WelcomeViewController: UIViewController, Navigable {
var data: AppData?
var appCoordinator: (any Coordinator)?
typealias T = AppData
override func viewDidLoad() {
//setUp()
}
}