首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >协议内部的Swift协议

协议内部的Swift协议
EN

Stack Overflow用户
提问于 2019-11-11 12:11:17
回答 2查看 101关注 0票数 1

我遇到了Swift协议的问题。我有这样的事情:

代码语言:javascript
复制
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

我怎么才能解决这个问题?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-11 12:29:39

使用关联类型 OnboardingPageViewModel类型ViewModel

编辑的

代码语言:javascript
复制
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
    }
}
票数 4
EN

Stack Overflow用户

发布于 2019-11-11 19:39:20

您可以通过删除关联类型来解决页面数组issue

代码语言:javascript
复制
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
    }
}

用法:

代码语言:javascript
复制
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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58801101

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档