Расширение протокола UICollectionViewDataSource для добавления реализаций по умолчанию

У меня довольно большой приложение, которое имеет много просмотров. Большинство представлений коллекции имеют одинаковые реализации для источника данных и делегата компоновки потока (одинаковые размеры, поля и т. д.). Я пытаюсь создать один протокол, который предоставляет реализации по умолчанию 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.

может кто-нибудь помочь?

3 ответов


Я знаю, что это не совсем то, что вы просили, я пытался - это не сработало. Сейчас ищу возможный ответ, потому что была похожая ситуация. Но я могу предложить вам такой вариант, как скрыть в вашем пользовательском протоколе всю логику для реализации делегата/источника данных.

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

, так что вам не нужно 'useProtocolForCollectionView:' на mutating

а так ты не нужен var reference = self и вы можете просто сказать self.userProtocolForCollectionView(collectionView)

особенно, если вы планируете реализовать этот протокол только с типами NSObject или class (UIViewController,UICollectionView и т. д.)