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?
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
}
}
I expect the problem is that this is an Objective-C protocol. Objective-C has never heard of a protocol extension. Therefore it has no knowledge that this protocol extension is injecting two functions into MyClass. It can't see them, and so as far as it is concerned, the protocol requirements are not satisfied.
To add to, but modify, what katleta3000 answered with, you can restrict a protocol to only apply to a 'class'
CollectionViewProtocol : class
so that you don't need 'useProtocolForCollectionView:'
to be mutating
Which then makes it so you don't need that var reference = self
and you can just say self.userProtocolForCollectionView(collectionView)
Especially if you only plan on implementing this protocol only with NSObject's or class types (UIViewController, UICollectionView, etc.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With