关联类型的Swift协议:如何在抽象方法中使用?

关联类型的Swift协议:如何在抽象方法中使用?,swift,protocols,associated-types,Swift,Protocols,Associated Types,我有两个协议,一个用于ViewModel,另一个用于将ViewModel类型作为关联类型的ConfigurableView: public protocol ViewModel {} public protocol ConfigurableView { associatedtype ViewModelType: ViewModel func configure(with viewModel: ViewModelType) } 在我用抽象模型配置抽象视图的方法中: let vie

我有两个协议,一个用于ViewModel,另一个用于将ViewModel类型作为关联类型的ConfigurableView:

public protocol ViewModel {}

public protocol ConfigurableView {

  associatedtype ViewModelType: ViewModel

  func configure(with viewModel: ViewModelType)

}
在我用抽象模型配置抽象视图的方法中:

let viewModel = getMyViewModel() // returns ViewModel

if let configurableView = cell as? ConfigurableView {
    configurableView.configure(with: viewModel)
}
我得到“协议'ConfigurableView'只能用作一般约束,因为它具有自身或关联的类型要求”


如果视图是ConfigurableView实例,我如何告诉编译器我希望使用该实例具有的任何关联类型来配置该视图?

除了类型约束之外,您不能使用通用协议。如果未定义泛型类型,编译器无法比较类型一致性。如果我理解正确,那么您需要定义generic
CellConfigurator
class。以下可能的解决方案之一:

1.单元和配置器抽象
希望能有帮助。祝您好运

除了类型约束之外,您不能使用通用协议。如果未定义泛型类型,编译器无法比较类型一致性。如果我理解正确,那么您需要定义generic
CellConfigurator
class。以下可能的解决方案之一:

1.单元和配置器抽象
希望能有帮助。祝你好运

我实际上找到了一个我认为不错的解决方案,它不需要对我的架构进行太多的修改。感谢@lib让我走上了正确的道路。诀窍在于,上面的协议没有associatedType需求,扩展将通用ViewModel强制转换为特定的associatedType。我相信这是类型擦除?但它看起来不像我读过的任何例子

public protocol ViewModel {}

/*
 This parent protocol exists so callers can call configure on
 a ConfigurableView they don't know the specific type of.
*/
public protocol AnyConfigurableView {

  func configure(with anyViewModel: ViewModel)

}

public protocol ConfigurableView: AnyConfigurableView {

  associatedtype ViewModelType: ViewModel

  func configure(with viewModel: ViewModelType)

}

/*
 This extension does the trick of converting from the generic
 form of ConfigurableView to the specific form.
 */
public extension ConfigurableView {

  func configure(with anyViewModel: ViewModel) {

    guard let viewModel = anyViewModel as? ViewModelType else {
      return
    }

    configure(with: viewModel)

  }

}
用法:

let viewModel = getViewModel()
(someView as? AnyConfigurableView)?.configure(with: viewModel)

实际上,我找到了一个我认为不错的解决方案,它不需要对我的架构进行太多的修改。感谢@lib让我走上了正确的道路。诀窍在于,上面的协议没有associatedType需求,扩展将通用ViewModel强制转换为特定的associatedType。我相信这是类型擦除?但它看起来不像我读过的任何例子

public protocol ViewModel {}

/*
 This parent protocol exists so callers can call configure on
 a ConfigurableView they don't know the specific type of.
*/
public protocol AnyConfigurableView {

  func configure(with anyViewModel: ViewModel)

}

public protocol ConfigurableView: AnyConfigurableView {

  associatedtype ViewModelType: ViewModel

  func configure(with viewModel: ViewModelType)

}

/*
 This extension does the trick of converting from the generic
 form of ConfigurableView to the specific form.
 */
public extension ConfigurableView {

  func configure(with anyViewModel: ViewModel) {

    guard let viewModel = anyViewModel as? ViewModelType else {
      return
    }

    configure(with: viewModel)

  }

}
用法:

let viewModel = getViewModel()
(someView as? AnyConfigurableView)?.configure(with: viewModel)