在我使用Swift 2的项目中,我正在处理2个协议MyViewControllerProtocol
和MyViewModelProtocol
。我希望所有视图控制器都符合MyViewControllerProtocol
。该协议将需要一个属性。该属性应符合MyViewModel
协议。
我在想什么会在这里工作:
protocol MyViewControllerProtocol {
var viewModel: <T:MyViewModelProtocol> { get set }
}
class MyCustomViewModel: MyViewModelProtocol {
// Implementation here
}
然后是视图控制器:
class ViewController: UIViewController, MyViewControllerProtocol {
var viewModel: MyCustomViewModel {
// Getter and Setter implementations here
}
}
我很可能会想到这个错误。这不会编译,我还没有看到这种类型的实现与属性一起。是否有其他模式可以完成我在这里尝试做的事情?
答案 0 :(得分:4)
如果您想拥有动态协议属性类型,那就是typealias
。
protocol MyViewModel {
var title: String { get set }
}
protocol MyViewController {
typealias MyViewModelType
var viewModel: MyViewModelType { get set }
}
class BaseViewController<T: MyViewModel>: MyViewController {
typealias MyViewModelType = T
var viewModel: T
init(_ viewModel: T) {
self.viewModel = viewModel
}
}
struct CarViewModel: MyViewModel {
var title: String = "Car"
}
struct BikeViewModel: MyViewModel {
var title: String = "Bike"
}
let car = BaseViewController(CarViewModel())
let bike = BaseViewController(BikeViewModel())
如果您尝试将其与不符合MyViewModel
协议的模型一起使用,则无效:
struct AnotherModel {
var title: String = "Another"
}
let another = BaseViewController(AnotherModel())
由于MyViewController
,因此您无法通过typealias
类型的参数传递视图控制器。这不起作用:
func something(vc: MyViewController) {
}
为什么不在没有typealias
的情况下采用更简单的方法。如果我理解正确,你就不需要它们。类似的东西:
protocol MyViewModel {
var title: String { get set }
}
protocol MyViewController {
var viewModel: MyViewModel { get set }
}
class BaseViewController: MyViewController {
var viewModel: MyViewModel
init(_ viewModel: MyViewModel) {
self.viewModel = viewModel
}
}
struct CarViewModel: MyViewModel {
var title: String = "Car"
}
struct BikeViewModel: MyViewModel {
var title: String = "Bike"
}
现在您可以使用MyViewController
协议作为变量类型:
let bike: MyViewController = BaseViewController(BikeViewModel())
let car: MyViewController = BaseViewController(CarViewModel())
您可以将其作为MyViewController
传递给某个函数:
func something(vc: MyViewController) {
}
你也不能这样做:
struct AnotherViewModel {
var title: String = "Another"
}
let another: MyViewController = BaseViewController(AnotherViewModel())
我错过了什么吗?我的意思是,关于你的泛型和类型限制?你有一些强制使用它的用例吗?
答案 1 :(得分:2)
协议的类型已被弃用,并替换为associatedtype。上面的答案现在写成:
protocol MyViewController {
associatedtype MyViewModelType
var viewModel: MyViewModelType { get set }
}
答案 2 :(得分:0)
Swift中的协议没有通用的尖括号。要使用通用行为,您必须使用typealias
:
protocol MyViewControllerProtocol {
typealias T: MyViewModelProtocol
var viewModel: T { get set }
}