Search code examples
swiftuicollectionviewswift-extensionsswift-protocolsprotocol-extension

Extend UICollectionViewDataSource Protocol to add default implementations


I have a fairly big application which has a lot of collection views. Most of the collection view have same implementations for Data Source and the Flow Layout Delegate (same sizes, margins etc). I am trying to create a single protocol which provides the default implementations of UICollectionViewDataSource and UICollectionViewDelegateFlowLayout. Here is my code.

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
}

The problem is that, the compiler complains that MyViewController does not conform to UICollectionViewDataSource. This should not be the case because I am clearly saying that add the default implementations if the type is TiledCollectionView.

Can some one help?


Solution

  • I know it's not exactly what you asked, I tried - it didn't work. Now looking for possible answer, because had similiar situation. But I can offer you such on option how to hide in your custom protocol all the logic for delegate/dataSource implementation.

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