ComposableDataSource
ComposableDataSource将常见的冗长的UICollectionView数据源和代理实现封装到一个更紧凑的构建器模式中
按需链式调用UICollectionView代理的方法
let dataSource = ComposableCollectionDataSource(....)
// chain selection delegate function
// chain cell size delegate function
// ... and so on ...
目录
先决条件
- Xcode 8.0或更高版本
- iOS 10.0或更高版本
安装
ComposableDataSource可通过CocoaPods获得。要安装它,只需将以下行添加到您的Podfile中
pod 'ComposableDataSource'
使用方法
创建一个可组合数据源有三个组成部分
- 设置一个视图模型以表示和配置单元格
- 创建一个可配置的单元格,使用基类BaseComposableCollectionViewCell
- 创建一个可组合数据源
步骤 1/3: 设置视图模型
实际上,这里有两个步骤
- 创建一个视图模型
- 创建一个模型(可选)
视图模型在单元格通过collectionView(_:cellForItemAt:)
出列时,用模型的信息装饰单元格。你的视图模型需要遵循BaseCollectionCellModel
协议。这样做需要你返回UICollectionView_class
// View Model
struct ChatroomViewModel: BaseCollectionCellModel {
func getCellClass() -> AnyComposableCellClass {
return ChatroomCell.self
}
let chatroom: Chatroom
}
// Model
struct Chatroom {
// ...
}
你的视图模型需要遵循BaseCollectionCellModel
并提供一个BaseComposableCollectionViewCell
子类的子类。类似于你通常使用collectionView.register:(forCellWithReuseIdentifier:)
步骤 2/3: 设置单元格
class ChatroomCell: BaseComposableCollectionViewCell {
override func configure(with item: BaseCollectionCellModel, at indexPath: IndexPath) {
let chatroomViewModel = item as! ChatroomViewModel
let chatroom = chatroomViewModel.chatroom
// Decorate cell using chatroom object
}
// UIViews ...
override func setupUIElements() {
super.setupUIElements()
// Use `super.containerView` instead of contentView to add your subviews
}
}
您的UICollectionView必须继承自BaseComposableCollectionViewCell。此外,利用两个可重写函数
func configure(with item: BaseCollectionCellModel, at indexPath: IndexPath) {
}
同样地
func setupUIElements() {
}
The configure(with:at:)
function is an overridable function from the BaseComposableCollectionViewCell
that is automatically called whenthe cell is dequeued with collectionView(_:cellForItemAt:)
. Use this to decorate your cell with data.
The setupUIElements()
function is an overridable function from the BaseComposableCollectionViewCell
that is automatically called when the cell is initialized. Add your subviews, constraints, etc. here.
步骤 3/3: 设置数据源
var dataSource: ComposableCollectionDataSource!
var collectionView : UICollectionView = ...
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
dataSource = setupDataSource()
}
....
private func setupDataSource() -> ComposableCollectionDataSource {
// Initialize double nested array of view models
// NOTE
// Each inner array represents each section of your data source
// in the order they are added
let models: [[ChatroomViewModel]] = [
// Section 0
[
ChatroomViewModel(chatroom: ....)
],
// Section 1, etc....
]
// Initialize array of supplementary models
// NOTE
// Each item represents the header and/or footer supplementary view
// for a specific section in the order they are added
let supplementaryModels: [GenericSupplementarySectionModel] = [....]
let dataSource = ComposableCollectionDataSource(collectionView: collectionView,
cellItems: models,
supplementarySectionItems: supplementaryModels)
.didSelectItem { (indexPath: IndexPath, model: BaseCollectionCellModel) in
// Handle selection at indexPath
}.sizeForItem { [unowned self] (indexPath: IndexPath, model: BaseCollectionCellModel) -> CGSize in
// Return size for cell at the specified indexPath
}.referenceSizeForHeader { [unowned self] (section: Int, model: BaseComposableSupplementaryViewModel) -> CGSize in
// Return size for supplementary header view at the specified indexPath
// If your data source will have supplementary models
}
// Chain more handlers ...
return dataSource
}
高级用法
添加到数据源
使用提供的公共API,向数据源添加新项非常简单。
首先,创建新的视图模型来表示您想要添加的单元格
let newSectionOfItems: [ChatroomViewModel] = [
ChatroomViewModel(chatroom: ....),
// Array of items...
]
然后使用由 ComposableCollectionDataSource
提供的API来添加项。在本示例中,我们将插入一个新的部分到第0个部分(实际上是在列表的顶部插入,并如预期将任何现有部分向下推)
let desiredSectionIndex: Int = 0
self.dataSource.insertNewSection(withCellItems: newSectionOfItems, supplementarySectionItem: nil,
atSection: desiredSectionIndex, completion: nil)
此外,还支持在变化的indexPaths和indices中插入视图模型
// Inserts cell view models at varying index paths
func insert(cellItems: [T], atIndexPaths indexPaths: [IndexPath],
updateStyle: DataSourceUpdateStyle, completion: OptionalCompletionHandler)
// Inserts supplementary section view models (Struct containing view models for header and/or footer supplementary views)
func insert(supplementarySectionItems: [S], atSections sections: [Int],
updateStyle: DataSourceUpdateStyle, completion: OptionalCompletionHandler)
更新数据源
更新数据源类似于添加项。但是,不是提供indexPaths或section indices来指定要插入的项的位置,提供的值将更新指定indexPaths/section indices的现有项。以下为更新部分的示例
let sectionIndicesToUpdate: [Int] = [0, 3]
let replacementItems: [[ChatroomViewModel]] = [
[
ChatroomViewModel(chatroom: ....),
// Array of items...
],
[
// Other items for next section in `sectionIndicesToUpdate`
]
]
self.dataSource.updateSections(atItemSectionIndices: sectionIndicesToUpdate,
newCellItems: replacementItems,
completion: nil)
此外,还支持在变化的indexPaths和indices中更新视图模型
public func updateCellItems(atIndexPaths indexPaths: [IndexPath],
newCellItems: [T],
updateStyle: DataSourceUpdateStyle = .withBatchUpdates,
completion: OptionalCompletionHandler)
public func updateSupplementarySectionsItems(atSections sections: [Int],
withNewSupplementarySectionItems supplementarySectionItems: [S],
updateStyle: DataSourceUpdateStyle = .withBatchUpdates,
completion: OptionalCompletionHandler)
从数据源删除
可以从数据源以多种方式删除内容,完全删除部分
let desiredSectionsToDelete: [Int] = [0, 2]
dataSource.deleteSections(atSectionIndices: desiredSectionsToDelete, completion: nil)
... 或者,按不同的indexPaths删除单元格视图模型,按不同的部分删除附加部分视图模型
// Deletes cell view models at varying index paths
func deleteCellItems(atIndexPaths indexPaths: [IndexPath],
updateStyle: DataSourceUpdateStyle,
completion: OptionalCompletionHandler)
// Deletes supplementary section view models (Struct containing view models for header and/or footer supplementary views)
func deleteSupplementarySectionItems(atSections sections: [Int],
updateStyle: DataSourceUpdateStyle,
completion: OptionalCompletionHandler)
空背景视图
如果您想在dataSource为空时显示某种视图,请这样做
let emptyView = UILabel()
emptyView.text = "Still loading data... :)"
emptyView.font = UIFont.boldSystemFont(ofSize: 25)
emptyView.numberOfLines = 0
emptyView.textAlignment = .center
dataSource.emptyDataSourceView = emptyView
完整文档
查看完整文档 在此
示例
要运行示例项目,首先克隆仓库,然后从示例目录运行pod install
。
作者
ChrishonWyllie, [email protected]
许可证
ComposableDataSource遵循MIT许可证。有关更多信息,请参阅LICENSE文件。