Расширьте протокол 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: класс
так что тебе не нужно 'useProtocolForCollectionView:'
быть mutating
Что делает его таким, что вам это не нужно var reference = self
и вы можете просто сказать self.userProtocolForCollectionView(collectionView)
Особенно, если вы планируете реализовать этот протокол только с NSObject или типами классов (UIViewController, UICollectionView и т. Д.)