Last active
June 27, 2018 01:51
-
-
Save aybekckaya/62c74a0475e58937710ef015391bfda9 to your computer and use it in GitHub Desktop.
Collection view with blocks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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