如何将通用数据注入视图控制器?

问题描述 投票:0回答:1

我正在尝试使用通用参数将通用数据注入视图控制器

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()
    }
}
swift generics protocols
1个回答
0
投票

您可以向

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()
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.