Skip to content

Instantly share code, notes, and snippets.

@aybekckaya
Last active June 27, 2018 01:51
Show Gist options
  • Save aybekckaya/62c74a0475e58937710ef015391bfda9 to your computer and use it in GitHub Desktop.
Save aybekckaya/62c74a0475e58937710ef015391bfda9 to your computer and use it in GitHub Desktop.
Collection view with blocks
//
// CollectionView.swift
// Trendyol
//
// Created by aybek can kaya on 12/06/2018.
// Copyright © 2018 aybek can kaya. All rights reserved.
//
import UIKit
// Model conforms this protocol
protocol Listable {
var className:String { get }
static var className:String { get }
}
extension Listable {
var className: String { return String(describing: type(of: self)) }
static var className: String { return String(describing: self) }
}
protocol HeaderViewListable {
var subModels:[Listable] { get set }
}
protocol ViewControllerAssignable {
func assignedViewOnTap(parameters:HeaderViewListable...)
}
class CollectionView: UICollectionView, UICollectionViewDelegate , UICollectionViewDataSource , UICollectionViewDelegateFlowLayout {
static let defaultInsets : UIEdgeInsets = UIEdgeInsetsMake(4, 4, 4, 4)
static let defaultMinimumSpacing : CGFloat = 4
fileprivate var cellAtIndexPath:((IndexPath)->(UICollectionViewCell)?)? = nil
fileprivate var sizeAtIndexPath:((IndexPath)->(CGSize)?)? = nil
fileprivate var didSelectItem:((IndexPath)->Void)? = nil
fileprivate var headerViewAtIndexPath: ((IndexPath)->(UICollectionReusableView )?)? = nil
fileprivate var edgeInsetsAtIndexPath: ((Int)->(UIEdgeInsets )?)? = nil
fileprivate var headerSizeAtIndex: ((Int)->(CGSize)?)? = nil
fileprivate var items:[Listable] = []
fileprivate var headerViewItems:[HeaderViewListable] = []
fileprivate var sizeItem:CGSize = CGSize.zero
fileprivate var insetsSection:UIEdgeInsets = UIEdgeInsets.zero
fileprivate var minimumSpacing:CGFloat = 0
fileprivate var pagingCollectionViewEnabled:Bool = false
fileprivate var isLoadingData:Bool = false
fileprivate var currentPage:Int = 1
fileprivate var shouldLoadPage: ((Int)->Void)? = nil
// getters
var pageCurrent:Int {
return currentPage
}
fileprivate enum CollectionViewType {
case undefined
case threeRowCellsWithHeader // instagram style :)
}
fileprivate var type:CollectionViewType = CollectionViewType.undefined
func collectionViewWithHeaderThreeRowCells<G:HeaderViewListable>(items:[G] , headerViewAtIndexPath:@escaping (_ indexPath:IndexPath)->(UICollectionReusableView), cellAtIndexPath:@escaping (_ indexPath:IndexPath)->(UICollectionViewCell?) , sizeAtIndexPath: @escaping (_ indexPath:IndexPath)->(CGSize) , headerSize:@escaping (_ section:Int)->(CGSize), edgeInsets:@escaping (_ section:Int)->(UIEdgeInsets) , didSelectItem: @escaping (_ indexPath:IndexPath)->Void ) {
minimumSpacing = CollectionView.defaultMinimumSpacing
self.type = CollectionViewType.threeRowCellsWithHeader
self.headerSizeAtIndex = headerSize
self.cellAtIndexPath = cellAtIndexPath
self.headerViewItems = items
self.sizeAtIndexPath = sizeAtIndexPath
self.didSelectItem = didSelectItem
self.edgeInsetsAtIndexPath = edgeInsets
self.headerViewAtIndexPath = headerViewAtIndexPath
setUp()
self.reloadData()
}
func pagingEnabled(shouldLoadNewPage: @escaping (_ pageIndex:Int)->Void) {
pagingCollectionViewEnabled = true
self.shouldLoadPage = shouldLoadNewPage
}
func startLoadingNewPage() {
isLoadingData = true
}
func finishLoadingNewPage() {
if isLoadingData == false { return }
isLoadingData = false
}
private func setUp() {
self.delegate = self
self.dataSource = self
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
if self.type == .threeRowCellsWithHeader {
return self.headerViewItems.count
}
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if self.type == .threeRowCellsWithHeader {
return headerViewItems[section].subModels.count
}
return items.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let collectionViewCell = cellAtIndexPath!(indexPath) {
return collectionViewCell
}
return UICollectionViewCell()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
if self.type == .threeRowCellsWithHeader {
return self.edgeInsetsAtIndexPath!(section)!
}
return insetsSection
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let selectionBlock = didSelectItem else { return }
selectionBlock(indexPath)
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return sizeAtIndexPath!(indexPath)!
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
//return 100
return minimumSpacing
}
func collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
//return 100
return minimumSpacing
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if self.type == .threeRowCellsWithHeader {
return headerViewAtIndexPath!(indexPath as IndexPath)!
}
return UICollectionReusableView()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
// return CGSize(width:100 , height:100)
if self.type == .threeRowCellsWithHeader {
return headerSizeAtIndex!(section)!
}
return CGSize.zero
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
guard pagingCollectionViewEnabled == true , isLoadingData == false else { return }
print("item Count: \(items.count) , indexPathRow: \(indexPath.row)")
if indexPath.row + 1 >= items.count {
currentPage += 1
shouldLoadPage!(currentPage)
}
}
}
// Registrable
extension CollectionView {
func registerCollectionViewCell(cellIndentifier:String) {
let nib = UINib(nibName: cellIndentifier, bundle: nil)
self.register(nib, forCellWithReuseIdentifier: cellIndentifier)
}
func registerCollectionHeaderView(identifier:String) {
let nib = UINib(nibName: identifier, bundle: nil)
self.register(nib, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader , withReuseIdentifier: identifier)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment