【发布时间】:2017-09-07 01:03:40
【问题描述】:
所以我试图理解通用协议和类:
protocol ListPresenterType where View.PDO.SW == Dispatcher.SW {
associatedtype Dispatcher: ListDispatcherType
associatedtype View: ListViewType
init(dispatcher: Dispatcher, state: @escaping (_ state: AppState)->(ListState<Dispatcher.SW>))
func attachView(_ view: View)
...
}
我从另一个泛型类启动它:
class AbstractListViewController<Presenter: ListPresenterType, PDO: ListPDOCommonType, ...>: ListViewType, ... where PDO.SW == Presenter.Dispatcher.SW, ... {
func configure(withBla: bla) {
...
presenter = Presenter(dispatcher: dispatcher, state: state)
}
func someFunc() {
presenter.attachView(self) // ERROR: Cannot invoke 'attachView' with an argument list of type ...
}
据我了解,我正在尝试初始化一个符合通用协议的类型,它工作得很好,但是 View 的类型必须与我在 attachView(:) 中尝试提供的内容不一致。
然后我尝试用具体视图初始化它,更改init:
init(dispatcher: Dispatcher, view: View, state: @escaping (_ state: AppState)->(ListState<Dispatcher.SW>)) {
self.view = view
...
}
在AbstractListViewController:
presenter = Presenter(dispatcher: dispatcher, view: self, state: state)
得到这个臭名昭著的错误:
Non-nominal type 'Presenter' does not support explicit initialization
以下是相关游乐场的要点:
- 成功初始化(虽然不能调用
attachView(:))https://gist.github.com/nikans/0fde838846ffa9ff2da48c923f850625 - 初始化失败并出现上述错误:https://gist.github.com/nikans/53c3ea146ceb12dc8461f7ba8a81793d
请注意,每个空协议实际上都是一个通用协议,我只是删除了不必要的细节。
我想了解:
- 是什么让“标称”类型突然变成“非标称”(没什么好奇怪的,它是符合通用协议的通用参数,但我不明白其中的因果关系)。
- 我听说过一些关于类型擦除的内容,但不太了解它是否适用于此。
谢谢。
【问题讨论】:
-
与其显示没有上下文的代码的 sn-ps,您能否显示足够的实际细节以允许其他人重现?
-
好主意,但由于所有对象都是通用的,并且取决于其他类型的类型,它可能要么是很多代码,要么是不够详细。我会尝试创建一个游乐场。
-
UPD:我用最少的可重现代码添加了要点
-
嗯。 Swift 版本重要吗?在您的“初始化失败并出现上述错误”中,我得到的是
cannot invoke initializer for type 'Presenter' with an argument list of type ... expected an argument list of type '(dispatcher: Self.Dispatcher, view: Self.View)'和cannot invoke 'attachView' with an argument list of type ... expected an argument list of type '(Presenter.View)' -
我使用 swift 3,但使用 xcode 9 beta 6 进行编译。这整件事在 xcode 8 中不起作用,不知道游乐场。我会检查的。
标签: swift generics xcode9beta6