Swift:Generic Protocol无法使用类型的参数列表调用

问题描述 投票:0回答:1

尝试使用关联类型创建通用协议。

当我尝试从委托访问方法时出现错误:

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)'
    }
}

我有一种感觉,我错过了一些东西。不带参数的方法编译得很好;但是,如果我调用一个确实采取调整的方法,我会收到编译错误。

swift xcode generics swift4
1个回答
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
© www.soinside.com 2019 - 2024. All rights reserved.