Swift 2协议 - 具有通用类型的属性?

时间:2015-07-30 01:38:03

标签: swift2

在我使用Swift 2的项目中,我正在处理2个协议MyViewControllerProtocolMyViewModelProtocol。我希望所有视图控制器都符合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
    }
}

我很可能会想到这个错误。这不会编译,我还没有看到这种类型的实现与属性一起。是否有其他模式可以完成我在这里尝试做的事情?

3 个答案:

答案 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 }
}