【发布时间】:2018-11-15 22:28:38
【问题描述】:
我为一个协议添加了一个协议扩展,它的关联类型称为PickerType。我写了一个函数的重新实现,refresh(:,completion:),它在协议中定义并在不同的协议扩展中实现。
但是当我调用 refresh(:,completion:) 时,我的新扩展中的函数不会被调用,除非编译器知道 PickerType 是什么类型。我写了以下内容:
extension PickerItemProvider where PickerType: Equatable & SyncableEntity {
func refresh(_ sender: Any, completion: (() -> Void)?) {
print("we're trying to have this implementation called")
PickerType.startSync()
}
}
如果我在 PickerSectionProvider<ObservationType> 上调用 refresh(:,completion:)(请参阅下面我的 Playground 中的代码),它会像我预期的那样被调用,但当我在 ItemProvider 上调用 refresh(:,completion:) 时不会调用,这是一个通用类型必须符合PickerItemProvider(再次参见下面的代码)。
// We are trying to get our pickers to sync their provided type when you pull to refresh. But the implementation of refresh(:, completion:) that we added doesn’t get called.
import Foundation
protocol PickerItemProvider: class {
associatedtype PickerType
func findItem(by identifier: NSNumber) -> PickerType?
func itemAt(_ indexPath: IndexPath) -> PickerType?
func refresh(_ sender: Any, completion: (() -> Void)?)
}
extension PickerItemProvider {
func findItem(by identifier: NSNumber) -> PickerType? {
return nil
}
public func refresh(_ sender: Any, completion: (() -> Void)?) {
print("the default refresh implementation")
}
}
public class PickerSectionProvider<ProvidedType: Equatable> : PickerItemProvider {
func itemAt(_ indexPath: IndexPath) -> ProvidedType? {
return nil
}
}
extension PickerItemProvider where PickerType: Equatable & SyncableEntity {
func refresh(_ sender: Any, completion: (() -> Void)?) {
print("we’re trying to have this implementation called instead of the above implementation of refresh")
PickerType.startSync()
}
}
protocol SyncableEntity {
static func startSync()
}
extension SyncableEntity {
static func startSync() {
}
}
class ObservationType: Equatable, SyncableEntity {
}
func ==(lhs: ObservationType, rhs: ObservationType) -> Bool {
return false
}
class GenericPickerViewController<PickerType: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == PickerType {
var itemProvider: ItemProvider?
init() {
}
func foo() {
// Why doesn’t the implementation of refresh(:,completion:) we added get called here?
itemProvider?.refresh("dummy sender") {
}
}
}
class PopupPickerRow<T: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == T {
var pickerController = GenericPickerViewController<T, ItemProvider>()
}
let pickerSectionProvider = PickerSectionProvider<ObservationType>()
let row = PopupPickerRow<ObservationType, PickerSectionProvider<ObservationType>>()
row.pickerController.itemProvider = pickerSectionProvider
row.pickerController.foo()
【问题讨论】:
标签: swift