扩展 UICollectionViewDataSource 协议以添加默认实现
Posted
技术标签:
【中文标题】扩展 UICollectionViewDataSource 协议以添加默认实现【英文标题】:Extend UICollectionViewDataSource Protocol to add default implementations 【发布时间】:2015-10-08 09:00:42 【问题描述】:我有一个相当大的应用程序,它有很多集合视图。大多数集合视图对数据源和流布局委托具有相同的实现(相同的大小、边距等)。我正在尝试创建一个提供 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,则添加默认实现。
有人可以帮忙吗?
【问题讨论】:
【参考方案1】:我知道这与您所要求的不完全一样,我试过了,但没有奏效。现在寻找可能的答案,因为有类似的情况。但是我可以为您提供这样的选项,如何在您的自定义协议中隐藏委托/数据源实现的所有逻辑。
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
【讨论】:
这似乎是添加装饰器的好模式,就像 Python 或 Java 中的装饰器一样。继续添加定义特定行为的协议,单个方法调用 (useProtocolFor....) 可以添加该行为。@suparngp
并非如此。如果您在协议 (var handler: CollectionViewProtocolHandler!
) 中声明一个变量 - 您无法在扩展中实现它 - 因此您必须手动将其添加到您的类中。至少你不能没有它来构建你的项目。如果 Apple 在协议中添加声明块,当您像在 Ruby 中一样继承它时,那就太好了 - 这样您就可以看到所有扩展的变量和函数,并可以选择覆盖它们。【参考方案2】:
我预计问题在于这是一个 Objective-C 协议。 Objective-C 从未听说过协议扩展。因此它不知道这个协议扩展正在向 MyClass 注入两个函数。它看不到它们,就它而言,不满足协议要求。
【讨论】:
假设你是对的,当我尝试为 UICollectionViewDataSource 进行默认实现时,他显示错误“候选人不是@objc
,但协议需要它”。当我将@objc
属性添加到协议函数时,它表示协议扩展的成员不能声明为@objc
。例如,我可以实现 UIAlertViewDelegate。【参考方案3】:
要添加但修改 katleta3000 回答的内容,您可以将协议限制为仅适用于“类”
CollectionViewProtocol : 类
这样您就不需要 'useProtocolForCollectionView:'
成为 mutating
这样你就不需要var reference = self
,你可以直接说self.userProtocolForCollectionView(collectionView)
特别是如果您只打算使用 NSObject 或类类型(UIViewController、UICollectionView 等)实现此协议
【讨论】:
以上是关于扩展 UICollectionViewDataSource 协议以添加默认实现的主要内容,如果未能解决你的问题,请参考以下文章
以编程方式从 collectionView 内的自定义 tableView 中进行 Segue
Kotlin扩展函数总结 ★ ( 超类扩展函数 | 私有扩展函数 | 泛型扩展函数 | 扩展属性 | 定义扩展文件 | infix 关键字用法 | 重命名扩展函数 | 标准库扩展函数 )
Kotlin扩展函数总结 ★ ( 超类扩展函数 | 私有扩展函数 | 泛型扩展函数 | 扩展属性 | 定义扩展文件 | infix 关键字用法 | 重命名扩展函数 | 标准库扩展函数 )
GroovyGroovy 扩展方法 ( 扩展静态方法示例 | 扩展实例方法示例 | 扩展实例方法与扩展静态方法代码相同 )