纯 Swift 编写的官方 UICollectionView API 轻量级美丽包装。
PulsarKit 是什么?
PulsarKit 是官方 UICollectionView API 简洁且美丽的包装,它完全用 Swift 语言编写。PulsarKit 是一个库,使您可以**简单地使用模型填充和更新**集合视图。
此框架受到了更轻量级的视图控制器和Xamarin 平台中 UITableViewSource 和 UICollectionViewSource 的启发。
内容
介绍
永远不再 实现UICollectionViewDataSource、UICollectionViewDelegate和UICollectionViewDelegateFlowLayout。
PulsarKit是一个小巧而专注的库,允许您从您的模型中填充和更新UICollectionView视图。忘记dequeuing和cell的类型转换。忘记将IndexPath转换为模型对象。PulsarKit将为您提供正确类型的dequeued视图和对应的模型对象,以索引路径为准。您可以专注于将自定义数据应用于自定义视图。
特性高亮
- 不再需要UICollectionViewDataSource/UICollectionViewDelegate
- 流畅接口配置(
.when(Model).use(Cell)
) - 轻松插入、更新、删除和移动段落和行(
source.add(model: ...)
) - 轻松重新排序collection view单元格和段落
- 轻松并且粒度细行事件处理(
.on.didSelect
) - 现成可用的视图控制器
- 强大的插件系统
需求
PulsarKit 1.3.x 兼容
- Swift 5.2+
- iOS 11+
- Xcode 11.4+
通信
- 如果您需要有关PulsarKit功能的帮助,请打开一个问题。
- 如果您想讨论功能请求,请打开一个问题。
- 如果您发现了一个错误,请打开一个问题。越详细越好!
- 如果您需要查找或理解一个API,请检查我们的文档或Apple的文档,PulsarKit是基于此构建的。
- 如果您想要贡献,提交一个pull request。
安装
PulsarKit 可通过 CocoaPods 获得。CocoaPods 是 Cocoa 项目的依赖管理工具。您可以使用以下命令安装它:
$ gem install cocoapods
要使用 CocoaPods 将 PulsarKit 集成到您的 Xcode 项目中,请在您的 Podfile 中指定它:
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!
target '<target>' do
pod 'PulsarKit'
end
然后,运行以下命令
$ pod install
用法
为了使用 PulsarKit,您需要遵循以下简单的 5 个步骤:
- 使您的模型符合
Hashable
协议 - 使您的单元格或模型符合
Bindable
协议 - 初始化一个
CollectionSource
的新实例 - 注册单元格类
- 用您的模型填充源
CollectionSource
是管理 UICollectionView
状态的主要类。所需的所有操作只初始化一个带 UICollectionView
实例的 source。
基本用法
带有可绑定单元格的示例
import PulsarKit
// 1. Conform your models to the `Hashable` protocol
struct User: Hashable {
let id: String
let name: String
}
// your custom cell class
class UserCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var nameLabel: UILabel!
}
// 2. Conform your cells to the `Bindable` protocol
extension UserCollectionViewCell: Bindable {
func bind(to element: User) {
nameLabel.text = element.name
}
}
class MyViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
// 3. Initialize a new instance of `CollectionSource`
lazy var source = CollectionSource(container: collectionView)
override func viewDidLoad() {
super.viewDidLoad()
// 4. Register cells classes
// the code below tells source to show a `UserCollectionViewCell`
// for every instance of `User` you add to source.
source.when(User.self).use(UserCollectionViewCell.self).withCellBinder()
// fetch users
fetchUsersFromNetwork()
}
func fetchUsersFromNetwork() {
userProvider.loadAll { [weak self] (users: [User]) in
// 5. Populate the source with your models
self?.source.add(models: users)
self?.source.update()
}
}
}
带有可绑定模型的示例
import PulsarKit
// 1. Conform your models to the `Hashable` protocol
struct Order: Hashable {
let id: String
let number: Int
}
// 2. Conform your models to the `Bindable` protocol
extension Order: Bindable {
func bind(to element: OrderCollectionViewCell) {
element.numberLabel.text = "\(number)"
}
}
// your cell class
class OrderCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var numberLabel: UILabel!
}
class MyViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
// 3. Initialize a new instance of `CollectionSource`
lazy var source = CollectionSource(container: collectionView)
override func viewDidLoad() {
super.viewDidLoad()
// 4. Register cells classes
// the code below tells source to show a `OrderCollectionViewCell`
// for every instance of `Order` you add to source.
source.when(Order.self).use(OrderCollectionViewCell.self).withModelBinder()
// fetch order
fetchOrders()
}
func fetchOrders() {
orderProvider.loadAll { [weak self] (orders: [Order]) in
// 5. Populate the source with your models
self?.source.add(models: orders)
self?.source.update()
}
}
}
事件处理
单元格选择
let user1 = User(id: 1, name: "Guest")
let descriptor = source.when(User.self).use(UserCollectionViewCell.self).withCellBinder()
// the callback is called when user did tap on any cell of type `UserCollectionViewCell`
descriptor.on.didSelect { context in
print("model: \(context.model)")
print("indexPath: \(context.indexPath)")
}
// the callback is callend when user did tap on a cell `binded` with a specific instance of user
descriptor.on(model: user1).didSelect { context in
print("model: \(context.model)")
print("indexPath: \(context.indexPath)")
}
// the callback is callend when user did tap on any cell
source.on.didSelect { _ in
print("model: \(context.model)")
print("indexPath: \(context.indexPath)")
}
其他事件
let descriptor = source.when(User.self).use(UserCollectionViewCell.self).withCellBinder()
// the callback is called when before adding a cell to collection view
descriptor.on.willDisplay { context in
print("cell: \(context.cell)")
print("model: \(context.model)")
print("indexPath: \(context.indexPath)")
}
单元格大小
PulsarKit 支持不同类型的单元格大小。您可以通过实现 Sizable
协议来提供您自定义的大小。默认情况下,PulsarKit 使用 TableSize
布局,该布局使用自动布局来计算高度和集合视图的宽度作为单元格的宽度。
PulsarKit 有 6 个现成的尺寸
AutolayoutSize
:使用自动布局来评估单元格的宽度和高度ContainerSize
:使用集合视图的边界作为单元格大小TableSize
:使用自动布局计算高度,并使用集合视图边界作为宽度SegmentedSize
:将集合视图边界大小分成相等的部分FixedSize
:为所有单元格类型提供固定的宽度和高度(如果计划所有单元格尺寸相同,则更快)CompositeSize
:一种特殊的大小,用于评估两种尺寸的组合
固定大小
let descriptor = source.when(User.self).use(UserCollectionViewCell.self).withCellBinder()
// fixed cell sizing
let fixed = FixedSize(width: 40, height: 50)
// set to descriptor
descriptor.set(sizeable: fixed)
组合大小
let descriptor = source.when(User.self).use(UserCollectionViewCell.self).withCellBinder()
// sizing composition
let container = ContainerSize() // it uses collection view bounds
let fixed = FixedSize(height: 50) // fixed height size
let composite = CompositeSize(widthSize: container, heightSize: fixed)
// set to descriptor
descriptor.set(sizeable: composite)
自定义大小
import PulsarKit
class MyCustomSize: Sizable {
public func size<View: UIView>(for view: View, descriptor: Descriptor, model: AnyHashable, in container: UIScrollView) -> CGSize {
// your custom logic here
}
}
// ....
let descriptor = source.when(User.self).use(UserCollectionViewCell.self).withCellBinder()
descriptor.set(sizeable: MyCustomSize())
特定模型的尺寸
// your models instances
let user1 = User(id: 1, name: "John")
let user2 = User(id: 1, name: "Jim")
let descriptor = source.when(User.self).use(UserCollectionViewCell.self).withCellBinder()
// set to descriptor
descriptor.set(sizeable: FixedSize(width: 300, height: 50), for: user1) // <- user 1
descriptor.set(sizeable: FixedSize(width: 50, height: 320), for: user2) // <- user 2
插件
PulsarKit拥有一个强大的插件系统,允许您添加新功能和行为。您可以通过实现SourcePlugin
协议来提供您的自定义插件。
PulsarKit提供了4个可直接使用的插件
PageControlPlugin
:保持UICollectionView页面和UIPageControl同步KeyboardHandlerPlugin
:防止键盘滑动问题并覆盖cell中的UITextField/UITextViewInfiniteScrollingPlugin
:启用无限滚动处理GroupedCollectionPlugin
:模拟分组表格视图的行为
插件使用示例
var infinite = InfiniteScrollingPlugin { source in
self.fetchMoreUsers { (users: [User]) in
self.source.add(models: users)
self.source.update()
}
}
source.add(plugin: infinite)
作者
Massimo Oliviero, [email protected]
许可证
PulsarKit在MIT许可证下可用。有关更多信息,请参阅LICENSE文件。