gpt4 book ai didi

swift - 关联类型符合协议(protocol)和依赖注入(inject)问题

转载 作者:可可西里 更新时间:2023-11-01 01:57:49 25 4
gpt4 key购买 nike

我正在研究依赖注入(inject),目前正在更新我的项目以利用它。但是,我在关联类型和协议(protocol)符合方面遇到了问题。

我创建了一个快速演示项目,并创建了一些协议(protocol)和扩展,以便符合我的协议(protocol) ViewModelBased 的 View Controller 必须实现关联类型。理想情况下,我希望此关联类型符合 viewModel。这是我目前所拥有的

protocol ViewModel {
associatedtype Services
init (withServices services: Services)
}

protocol ViewModelBased: class {
associatedtype ViewModelType
var viewModel: ViewModelType { get set }
}

extension ViewModelBased where Self: UIViewController{
static func instantiateController(with viewModel : ViewModelType) -> Self {

// I have created UIStoryboard extension to allow for easy opening of view controllers
// in storyboard
let viewController : Self = UIStoryboard.mainStoryboard.instantiateViewController()
viewController.viewModel = viewModel
return viewController
}
}

所以我的应用程序中的所有 viewModel 都符合 ViewModel,这迫使它们实现服务类型。例如,我的 LoginModel 看起来像这样

 struct LoginModel : ViewModel{

// service type
typealias Services = LoginService

// init service
var services : LoginService
init(withServices services: LoginService) {
self.services = services
}

/// calls login service - attempts login api
func attemptLogin() {
services.login()
}
}

所以这里有一个实现这个的 viewController 的例子

class SecondController: UIViewController, ViewModelBased  {

var viewModel: LoginModel!

override func viewDidLoad() {
super.viewDidLoad()

}

@IBAction func loginTest() {
viewModel.services.onLoginSuccess = { isVerified in

print(isVerified)
}

viewModel.services.onLoginFailure = { errorCode in

print(errorCode)
}

viewModel.attemptLogin()
}
}

所以把它们放在一起,这允许应用程序像这样初始化一个 viewController 并传入一个 viewModel

   let loginModel = LoginModel(withServices: LoginService())
let controller = SecondController.instantiateController(with: loginModel)
self.navigationController?.pushViewController(controller, animated: true)

这一切都很好,但我遇到的问题是,关联的类型目前可以是任何类型。理想情况下,我希望此 associatedType 符合 ViewModel 协议(protocol)。但是当我尝试这个时

protocol ViewModelBased: class {
associatedtype ViewModelType : ViewModel
var viewModel: ViewModelType { get set }
}

我的 SecondController 现在抛出错误并强制我初始化 LoginModel

var viewModel : LoginModel = LoginModel(withServices: LoginService())

但这不再使用依赖注入(inject),因为 viewController 现在负责创建 viewModel 实例并了解 viewModel 类的行为。

有什么办法可以解决这个问题吗?如果有人能给我一些关于我做错了什么的信息,我将不胜感激。

最佳答案

您可以扩展 Optional 以有条件地符合 ViewModel:

extension Optional: ViewModel where Wrapped: ViewModel {

typealias Services = Wrapped.Services

init(withServices services: Services) {
self = Wrapped(withServices: services)
}

}

现在您的 SecondController 将其模型声明为 var viewModel: LoginModel?,默认情况下将其初始化为 nil,同时仍确保其ViewModelType 是一个 ViewModel,实际上不需要创建它的实例。

关于swift - 关联类型符合协议(protocol)和依赖注入(inject)问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49938246/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com