All Projects → maxoly → Pulsarkit

maxoly / Pulsarkit

Licence: mit
PulsarKit is a simple and beautiful wrapper around the official UICollectionView API written in pure Swift

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Pulsarkit

Skeletonview
☠️ An elegant way to show users that something is happening and also prepare them to which contents they are awaiting
Stars: ✭ 10,804 (+134950%)
Mutual labels:  ios-ui, uicollectionview
Parchment
A paging view controller with a highly customizable menu ✨
Stars: ✭ 2,812 (+35050%)
Mutual labels:  ios-ui, uicollectionview
Ehhorizontalselectionview
Horizontal table view style controller
Stars: ✭ 346 (+4225%)
Mutual labels:  ios-ui, uicollectionview
Tysnapshotscroll
一句代码保存截图,将 UIScrollView UITableView UICollectionView UIWebView WKWebView 网页 保存 为 长图 查看。Save the scroll view page as an image,support UIScrollView,UITableView,UICollectionView,UIWebView,WKWebView.(Support iOS13)
Stars: ✭ 709 (+8762.5%)
Mutual labels:  uicollectionview
Koyomi
Simple customizable calendar component in Swift 📆
Stars: ✭ 716 (+8850%)
Mutual labels:  uicollectionview
Xlpagertabstrip
Android PagerTabStrip for iOS.
Stars: ✭ 6,671 (+83287.5%)
Mutual labels:  ios-ui
Tbactionsheet
A Custom&Powerful Action Sheet For iOS. 一个 ActionSheet 满足所有样式!超高自由度的可定制!
Stars: ✭ 942 (+11675%)
Mutual labels:  ios-ui
Selectabletextview
A text view that supports selection and expansion
Stars: ✭ 626 (+7725%)
Mutual labels:  ios-ui
Cascadingtabledelegate
A no-nonsense way to write cleaner UITableViewDelegate and UITableViewDataSource in Swift.
Stars: ✭ 931 (+11537.5%)
Mutual labels:  ios-ui
Gravityslider
🔄 GravitySlider is a beautiful alternative to the standard UICollectionView flow layout.
Stars: ✭ 784 (+9700%)
Mutual labels:  uicollectionview
Viewanimator
ViewAnimator brings your UI to life with just one line
Stars: ✭ 6,592 (+82300%)
Mutual labels:  uicollectionview
Flix
iOS reusable form library in Swift.
Stars: ✭ 725 (+8962.5%)
Mutual labels:  uicollectionview
Changeset
Minimal edits from one collection to another
Stars: ✭ 807 (+9987.5%)
Mutual labels:  uicollectionview
Hwpanmodal
HWPanModal presents controller from bottom and drag to dismiss, high customize. iOS13 default modalPresentationStyle. 任意形式的底部弹框动画;头条、知乎、抖音弹出评论效果;地图浮层,iOS13 present默认模态效果。
Stars: ✭ 713 (+8812.5%)
Mutual labels:  ios-ui
Thinningcoordinator
The UITableView/UICollectionView dataSource/delegate thinning coordinator, help thinning your UIViewController!
Stars: ✭ 25 (+212.5%)
Mutual labels:  uicollectionview
Gltablecollectionview
Netflix and App Store like UITableView with UICollectionView, written in pure Swift 4.2
Stars: ✭ 709 (+8762.5%)
Mutual labels:  uicollectionview
Greedo Layout For Ios
Full aspect ratio grid layout for iOS
Stars: ✭ 837 (+10362.5%)
Mutual labels:  uicollectionview
Qmui ios
QMUI iOS——致力于提高项目 UI 开发效率的解决方案
Stars: ✭ 6,433 (+80312.5%)
Mutual labels:  ios-ui
Parade
Parallax Scroll-Jacking Effects Engine for iOS / tvOS
Stars: ✭ 754 (+9325%)
Mutual labels:  ios-ui
Cariocamenu
The fastest zero-tap iOS menu.
Stars: ✭ 785 (+9712.5%)
Mutual labels:  ios-ui

PulsarKit

Lightweight and beautiful wrapper around the official UICollectionView API written in pure Swift.


What is PulsarKit?

PulsarKit is a simple and beautiful wrapper around the official UICollectionView API written in pure Swift. PulsarKit is a library that lets you populate and update collection views simply using your models.

This framework is lightly inspire by Lighter view controllers and UITableViewSource and UICollectionViewSource in Xamarin Platform.

Contents

Introduction

Never implement UICollectionViewDataSource, UICollectionViewDelegate and UICollectionViewDelegateFlowLayout again.

PulsarKit is a small, focused library that lets you populate and update UICollectionView views from your models. Forget about dequeuing and type casting cells. Forget about converting an IndexPath to a model object. PulsarKit will hand you dequeued views of the correct type along with the right model object for the index path. You can focus on applying your custom data to your custom view.

Features Highlights

  • [x] No more UICollectionViewDataSource/UICollectionViewDelegate
  • [x] Fluent interface configuration (.when(Model).use(Cell))
  • [x] Easy section and row insertion, updation, deletion and movement (source.add(model: ...))
  • [x] Easy reordering of collection view cells and sections
  • [x] Easy and fine grained row event handling (.on.didSelect)
  • [x] Ready to use view controllers
  • [x] Powerful plugin system

Requirements

PulsarKit 1.3.x is compatible with:

  • Swift 5.0+
  • iOS 10+
  • Xcode 10.2+

Communication

  • If you need help with an PulsarKit feature, open an issue.
  • If you'd like to discuss a feature request, open an issue.
  • If you found a bug, open an issue. The more detail the better!
  • If you need to find or understand an API, check our documentation or Apple's documentation for UICollectionView, on top of which PulsarKit is built.
  • If you want to contribute, submit a pull request.

Installation

PulsarKit is available through CocoaPods. CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:

$ gem install cocoapods

To integrate PulsarKit into your Xcode project using CocoaPods, specify it in your Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!

target '<target>' do
pod 'PulsarKit'
end

Then, run the following command:

$ pod install

Usage

In order to use PulsarKit it is necessary to follow 5 simply steps:

  1. Conform your models to the Hashable protocol
  2. Conform your cells or models to the Bindable protocol
  3. Initialize a new instance of CollectionSource
  4. Register cells classes
  5. Populate the source with your models

The CollectionSource is the main class that manages the state of the UICollectionView. All that is required is to initialize a source with an instance of UICollectionView.

Basic usage

Example with Bindable cells

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()
      }
   }
}

Example with Bindable models

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()
      }
   }
}

Event Handling

Cell selection

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)")
}

Other events

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)")
}

Sizing cells

PulsarKit supports different kind of cell sizing. You can provide your custom sizing implementing Sizable protocol. By default PulsarKit uses the TableSize layout that uses autolayout to calculate height and the width of collection view as width of the cell.

PulsarKit has 6 ready-to-use sizes:

  • AutolayoutSize: uses autolayout to evaluate the width and the height of the cell
  • ContainerSize: uses the collection view bounds as cell size
  • TableSize: uses autolayout for height and collection view bounds for width
  • SegmentedSize: divides the collection view bounds size into equal parts
  • FixedSize: provide a fixed height/width for all cell types (faster if you plan to have all cell sized same)
  • CompositeSize: a special size that evaluates combinations of two sizes

Fixed sizing

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)

Composite sizing

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)

Custom sizing

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())

Sizing for a specific model

// 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

Plugins

PulsarKit has a powerful plugin system that allows you to add new features and behaviors. You can provide your custom plugin implementing SourcePlugin protocol.

PulsarKit has 4 ready-to-use plugins:

  • PageControlPlugin: mantains in sync the UICollectionView pages and UIPageControl
  • KeyboardHandlerPlugin: prevents issues of keyboard sliding up and cover UITextField/UITextView inside a cell
  • InfiniteScrollingPlugin: enables infinite scrolling handling
  • GroupedCollectionPlugin: mimics grouped table view style behavior

Plugin usage example

var infinite = InfiniteScrollingPlugin { source in
	self.fetchMoreUsers { (users: [User]) in
    	self.source.add(models: users)
        self.source.update()
    }
}

source.add(plugin: infinite)

Author

Massimo Oliviero, [email protected]

License

PulsarKit is available under the MIT license. See the See LICENSE file for more info.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].