Swift 协议中的协议
Swift protocol inside of protocol
我 运行 遇到了 Swift 协议的问题。我有这样的东西:
protocol OnboardingPage {
var viewModel: OnboardingPageViewModel! { get }
}
protocol OnboardingPageViewModel {
func getValue() -> Bool
}
// ---
class FirstNameViewController: UIViewController, OnboardingPage {
var viewModel: FirstNameViewModel!
}
class FirstNameViewModel: OnboardingPageViewModel {
func getValue() -> Bool {
return true
}
}
class GenderViewController: UIViewController, OnboardingPage {
var viewModel: GenderViewModel!
}
class GenderViewModel: OnboardingPageViewModel {
func getValue() -> Bool {
return false
}
}
我有一堆确认 OnboardingPage
协议的视图控制器,它们都有一个都符合 OnboardingPageViewModel
协议的视图模型。
但遗憾的是上面的代码不起作用:它说 FirstNameViewController
没有确认 OnboardingPage
协议,因为它的 viewModel
属性 类型为 FirstNameViewModel
而不是 OnboardingPageViewModel
- 即使 FirstNameViewModel
是 OnboardingPageViewModel
.
我该如何解决这个问题?
使用关联类型 OnboardingPageViewModel 类型 ViewModel
已编辑
protocol OnboardingPage {
associatedtype ViewModel: OnboardingPageViewModel
var viewModel: ViewModel { get }
}
protocol OnboardingPageViewModel {
func getValue() -> Bool
}
class FirstNameViewController: OnboardingPage {
let viewModel: FirstNameViewModel
init(viewModel: FirstNameViewModel) {
self.viewModel = viewModel
}
}
class FirstNameViewModel: OnboardingPageViewModel {
func getValue() -> Bool {
return true
}
}
class GenderViewController: OnboardingPage {
let viewModel: GenderViewModel
init(viewModel: GenderViewModel) {
self.viewModel = viewModel
}
}
class GenderViewModel: OnboardingPageViewModel {
func getValue() -> Bool {
return false
}
}
您可以通过删除 associatedtype:
来解决您的页面数组
protocol OnboardingPage {
var viewModel: OnboardingPageViewModel { get }
}
protocol OnboardingPageViewModel {
func getValue() -> Bool
}
class FirstNameViewModel: OnboardingPageViewModel {
func getValue() -> Bool {
return true
}
}
class FirstNameViewController: OnboardingPage {
let viewModel: OnboardingPageViewModel
init(viewModel: FirstNameViewModel) {
self.viewModel = viewModel
}
}
class GenderViewModel: OnboardingPageViewModel {
func getValue() -> Bool {
return false
}
}
class GenderViewController: OnboardingPage {
let viewModel: OnboardingPageViewModel
init(viewModel: GenderViewModel) {
self.viewModel = viewModel
}
}
用法:
let nameModel = FirstNameViewModel()
let genderModel = GenderViewModel()
let array: [OnboardingPage] = [FirstNameViewController(viewModel: nameModel), GenderViewController(viewModel: genderModel)]
for page in array {
print(page.viewModel.getValue())
}
但是,以这种方式,您的模型的具体类型将无法供 OnboardingPage
符合 类 的调用者使用。您可以尝试通过在 OnboardingPage
内实施访问者模式或增强其功能来解决它。
当然,您始终可以使用 Cruz 示例编写 let pages: [Any] = [FirstNameViewController(), GenderViewController()]
,但它很难看,如果可能,我强烈建议您不要在 API 中使用 Any
.
我 运行 遇到了 Swift 协议的问题。我有这样的东西:
protocol OnboardingPage {
var viewModel: OnboardingPageViewModel! { get }
}
protocol OnboardingPageViewModel {
func getValue() -> Bool
}
// ---
class FirstNameViewController: UIViewController, OnboardingPage {
var viewModel: FirstNameViewModel!
}
class FirstNameViewModel: OnboardingPageViewModel {
func getValue() -> Bool {
return true
}
}
class GenderViewController: UIViewController, OnboardingPage {
var viewModel: GenderViewModel!
}
class GenderViewModel: OnboardingPageViewModel {
func getValue() -> Bool {
return false
}
}
我有一堆确认 OnboardingPage
协议的视图控制器,它们都有一个都符合 OnboardingPageViewModel
协议的视图模型。
但遗憾的是上面的代码不起作用:它说 FirstNameViewController
没有确认 OnboardingPage
协议,因为它的 viewModel
属性 类型为 FirstNameViewModel
而不是 OnboardingPageViewModel
- 即使 FirstNameViewModel
是 OnboardingPageViewModel
.
我该如何解决这个问题?
使用关联类型 OnboardingPageViewModel 类型 ViewModel
已编辑
protocol OnboardingPage {
associatedtype ViewModel: OnboardingPageViewModel
var viewModel: ViewModel { get }
}
protocol OnboardingPageViewModel {
func getValue() -> Bool
}
class FirstNameViewController: OnboardingPage {
let viewModel: FirstNameViewModel
init(viewModel: FirstNameViewModel) {
self.viewModel = viewModel
}
}
class FirstNameViewModel: OnboardingPageViewModel {
func getValue() -> Bool {
return true
}
}
class GenderViewController: OnboardingPage {
let viewModel: GenderViewModel
init(viewModel: GenderViewModel) {
self.viewModel = viewModel
}
}
class GenderViewModel: OnboardingPageViewModel {
func getValue() -> Bool {
return false
}
}
您可以通过删除 associatedtype:
来解决您的页面数组protocol OnboardingPage {
var viewModel: OnboardingPageViewModel { get }
}
protocol OnboardingPageViewModel {
func getValue() -> Bool
}
class FirstNameViewModel: OnboardingPageViewModel {
func getValue() -> Bool {
return true
}
}
class FirstNameViewController: OnboardingPage {
let viewModel: OnboardingPageViewModel
init(viewModel: FirstNameViewModel) {
self.viewModel = viewModel
}
}
class GenderViewModel: OnboardingPageViewModel {
func getValue() -> Bool {
return false
}
}
class GenderViewController: OnboardingPage {
let viewModel: OnboardingPageViewModel
init(viewModel: GenderViewModel) {
self.viewModel = viewModel
}
}
用法:
let nameModel = FirstNameViewModel()
let genderModel = GenderViewModel()
let array: [OnboardingPage] = [FirstNameViewController(viewModel: nameModel), GenderViewController(viewModel: genderModel)]
for page in array {
print(page.viewModel.getValue())
}
但是,以这种方式,您的模型的具体类型将无法供 OnboardingPage
符合 类 的调用者使用。您可以尝试通过在 OnboardingPage
内实施访问者模式或增强其功能来解决它。
当然,您始终可以使用 Cruz 示例编写 let pages: [Any] = [FirstNameViewController(), GenderViewController()]
,但它很难看,如果可能,我强烈建议您不要在 API 中使用 Any
.