Swift 扩展UICollectionViewDataSource协议以添加默认实现

Swift 扩展UICollectionViewDataSource协议以添加默认实现,swift,uicollectionview,swift-extensions,swift-protocols,protocol-extension,Swift,Uicollectionview,Swift Extensions,Swift Protocols,Protocol Extension,我有一个相当大的应用程序,它有很多集合视图。对于数据源和流布局委托,大多数集合视图具有相同的实现(相同的大小、边距等)。我正在尝试创建一个协议,该协议提供UICollectionViewDataSource和UICollectionViewDelegateFlowLayout的默认实现。这是我的密码 protocol TiledCollectionView{} extension UICollectionViewDataSource where Self: TiledCollectionVie

我有一个相当大的应用程序,它有很多集合视图。对于数据源和流布局委托,大多数集合视图具有相同的实现(相同的大小、边距等)。我正在尝试创建一个协议,该协议提供UICollectionViewDataSource和UICollectionViewDelegateFlowLayout的默认实现。这是我的密码

protocol TiledCollectionView{}

extension UICollectionViewDataSource where Self: TiledCollectionView{
    //default implementation of the 3 methods to load the data ...
}
extension UICollectionViewDelegateFlowLayout where Self: TiledCollectionView {
    //default implementation for layout methods to set default margins etc...
}

class MyViewController: UIViewController, TiledCollectionView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{
    // the rest of the required logic for view controller
    // here I Don't implement any CollectionView methods since I have provided the default implementation already
}
问题是,编译器抱怨MyViewController不符合UICollectionViewDataSource。不应该是这种情况,因为我清楚地说,如果类型为TiledCollectionView,则添加默认实现


有人能帮忙吗?

我知道这不完全是你要的,我试过了——没用。现在正在寻找可能的答案,因为有相似的情况。但是我可以为您提供这样一个选项:如何在自定义协议中隐藏委托/数据源实现的所有逻辑

class CollectionViewProtocolHandler: NSObject, UICollectionViewDelegate, UICollectionViewDataSource  {

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 0
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        return UICollectionViewCell() // only for test
    }
}

protocol CollectionViewProtocol {
    var handler: CollectionViewProtocolHandler! {get set}
    mutating func useProtocolForCollectionView(collectionView: UICollectionView)
}

extension CollectionViewProtocol {
    mutating func useProtocolForCollectionView(collectionView: UICollectionView) {
        handler = CollectionViewProtocolHandler()
        collectionView.delegate = handler
        collectionView.dataSource = handler
    }
}

class ViewController: UIViewController, CollectionViewProtocol {
    var handler: CollectionViewProtocolHandler! // CollectionViewProtocol convenience

    override func viewDidLoad() {
        super.viewDidLoad()

        let collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: UICollectionViewFlowLayout())
        collectionView.backgroundColor = .redColor()
        view.addSubview(collectionView)
        var reference = self
        reference.useProtocolForCollectionView(collectionView) // for initialize protocol
    }
}

我想问题是这是一个Objective-C协议。Objective-C从未听说过协议扩展。因此,它不知道该协议扩展正在向MyClass中注入两个函数。它看不到它们,就其而言,协议要求未得到满足。

要添加但修改katleta3000回答的内容,可以限制协议仅适用于“类”

CollectionViewProtocol : class CollectionViewProtocol:类 这样您就不需要
'useProtocolForCollectionView:'
进行
变异

这样,您就不需要
var reference=self
,只需说
self.userProtocolForCollectionView(collectionView)


特别是,如果您只计划使用NSObject或类类型(UIViewController、UICollectionView等)实现此协议,那么假设您是对的,当我尝试对UICollectionViewDataSource进行默认实现时,他显示错误“候选者不是
@objc
,但协议需要它”。当我向协议函数添加
@objc
属性时,它表示协议扩展的成员不能声明为
@objc
。例如,我可以实现UIAlertViewDelegate,这似乎是添加装饰器的好模式,比如Python或Java中的装饰器。继续添加定义特定行为的协议,单个方法调用(useProtocolFor…)可以添加该行为。
@suparngp
并非所有。如果在协议中声明变量(
var-handler:CollectionViewProtocolHandler!
),则无法在扩展中实现该变量,因此必须手动将其添加到类中。至少你不能没有它来构建你的项目。如果苹果在协议中添加声明块,就像在Ruby中一样继承它,那就太好了,这样您就可以看到所有扩展变量和函数,并可以选择重写它们。