6

我有一个相当大的应用程序,它有很多集合视图。大多数集合视图对数据源和流布局委托具有相同的实现(相同的大小、边距等)。我正在尝试创建一个提供 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,则添加默认实现。

有人可以帮忙吗?

4

3 回答 3

6

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

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
    }
}
于 2015-10-08T09:28:08.740 回答
4

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

于 2015-10-08T09:34:50.960 回答
1

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

集合视图协议:类

'useProtocolForCollectionView:'这样你就不需要mutating

然后就可以了,所以你不需要那个var reference = self,你可以说self.userProtocolForCollectionView(collectionView)

尤其是如果您只打算使用 NSObject 或类类型(UIViewController、UICollectionView 等)实现此协议

于 2015-11-16T06:00:11.697 回答