尝试使用associatedtype创建通用协议。
当我尝试从委托访问方法时出现错误:
Cannot invoke 'numberOfSections' with an argument list of type '(containerView: UITableView)'
代码:
protocol ViewDelegate: class {
associatedtype ContainerView
associatedtype Model
func numberOfSections(containerView: ContainerView)
func aMethodThatTakesNoArugments()
}
class ViewController: UIViewController {
var newView = AnyView<ViewController>()
override func viewDidLoad() {
super.viewDidLoad()
newView.delegate = self
}
}
extension ViewController: ViewDelegate {
typealias ContainerView = UITableView
typealias Model = Int
func numberOfSections(containerView: ContainerView) {
// do something with containerView
}
func aMethodThatTakesNoArugments() {}
}
class AnyView<Delegate: ViewDelegate>: UIView {
weak var delegate: Delegate?
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func getData() {
delegate?.aMethodThatTakesNoArugments() // This compiles fine
delegate?.numberOfSections(containerView: UITableView()) // Get a compiler error on this line (I am passing an argument):
// Cannot invoke 'numberOfSections' with an argument list of type '(containerView: UITableView)'
}
}
我有一种感觉,我错过了一些东西。不带参数的方法编译得很好;但是,如果我调用一个确实采取调整的方法,我会收到编译错误。
答案 0 :(得分:1)
您的错误是由于编译器无法判断类型ContainerView
应该是什么。
您只为ViewController
定义它,但Delegate可以是任何类或结构,而不仅仅是ViewController。
有很多方法可以解决这个问题,但目前还不清楚你究竟要在这里完成什么,所以我只举几个例子:
正如@OOPer所提到的,你可以约束你的Delegate
泛型以强制符合UITableView:
class AnyView<Delegate: ViewDelegate>: UIView where Delegate.ContainerView == UITableView
类似的选择是简单地定义具有所需类型的协议:
protocol ViewDelegate: class {
func numberOfSections(containerView: ContainerView)
func aMethodThatTakesNoArugments()
}
如果您需要更多灵活性,另一个选择是添加另一个通用类型:
class AnyView<Delegate: ViewDelegate, ContainerViewType>: UIView where Delegate.ContainerView == ContainerViewType