Im trying to add a segmented control onto my header but I am having trouble doing this. In this example to make things simpler I am adding a Label but that is also not showing. Can someone tell me why this is not happening?
import UIKit
class SessionsViewController: UICollectionViewController , UICollectionViewDelegateFlowLayout {
override func viewDidLoad() {
super.viewDidLoad()
prepareCollectionView()
view.backgroundColor = UIColor.white
navigationController?.navigationBar.isTranslucent = true
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Log Out", style: .plain, target: self, action: #selector(handleLogout))
navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "plus") , style: .plain, target: self, action: nil)
navigationItem.rightBarButtonItem?.tintColor = UIColor.honePalette.accent
}
func prepareSegmentedControll()->UISegmentedControl{
let items = ["Future Sessions", "Past Sessions"]
let control = UISegmentedControl(items: items)
control.selectedSegmentIndex = 0
control.tintColor = UIColor.honePalette.accent
let font = UIFont.systemFont(ofSize: 12)
control.setTitleTextAttributes([NSFontAttributeName: font], for: .normal)
return control
}
func prepareCollectionView(){
collectionView?.backgroundColor = UIColor.white
collectionView?.alwaysBounceVertical = true
collectionView?.register(sessionsInfo.self, forCellWithReuseIdentifier: "cellId")
}
// return of the number per item per section
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
//this is when the collection is clicked
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let indexPath = collectionView.indexPathsForSelectedItems
print("this is index path:", indexPath)
}
// this is the cell of the collection returning initialized with the SessionsInfo
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let myCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as? sessionsInfo
myCell?.sessionLabel.text = "cell \(indexPath.row)"
return myCell!
}
// this is when the size of the cell returns
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width - 10, height: 80)
}
// return supplementary view
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "header", for: indexPath)
let label = UILabel(frame: headerView.bounds)
label.text = "Top View"
label.font = UIFont(name: "helvetica", size: 12)
label.textAlignment = .center
headerView.addSubview(label)
//headerView.headerLabel.text = "header"
return headerView
}
func handleLogout(){
BaseServices.baseServices.signOut()
present(LoginViewController(), animated: true, completion: nil)
}
}
class headerInfo : UICollectionReusableView{
override init(frame: CGRect) {
super.init(frame: frame)
setupHeader()
}
var headerLabel : UILabel = {
let label = UILabel()
label.text = "HEADER"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupHeader(){
backgroundColor = UIColor.honePalette.raindrops
addSubview(headerLabel)
addConstraints(NSLayoutConstraint.constraints( withVisualFormat: "H:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":headerLabel]))
addConstraints(NSLayoutConstraint.constraints( withVisualFormat: "V:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":headerLabel]))
}
}
class sessionsInfo: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupSessions()
}
var sessionLabel : UILabel = {
let label = UILabel()
label.text = "sessionView"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
var sessionTimeLabel : UILabel = {
let label = UILabel()
label.text = ""
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
var sessionLocationLabel : UILabel = {
let label = UILabel()
label.text = ""
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
func setupSessions(){
backgroundColor = UIColor.honePalette.raindrops
addSubview(sessionLabel)
addConstraints(NSLayoutConstraint.constraints( withVisualFormat: "H:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":sessionLabel]))
addConstraints(NSLayoutConstraint.constraints( withVisualFormat: "V:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":sessionLabel]))
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
I tried your code in a new project, and you are missing two key steps: registering the supplementary view and setting the size of your header.
In your prepareCollectionView function, you also need to register the header view:
collectionView?.register(headerInfo.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "header")
You also need to implement another delegate function giving the size of your header view:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width: 100, height: 100) // fix to be your intended size
}
Here is proof that it works. (I didn't have access to your custom colors, which is why everything is orange and gray.)
Related
I have a button embedded in a UICollectionViewCell with the below structure, when I try to tap button, neither the button UI changes nor the associated function gets called, this behaviour is seen in iOS 12 (iPhone 8) and not in iOS 10 (iPhone 5)
UITableView > UITableViewCell > UICollectionView > UICollectionViewCell > UIButton
The following screenshot shows the tableViewCell with collectionViewCells.
Below is the code:
TableView
class AppointmentTVC: UITableViewController {
var appointmentTimesCollectionTVCell = AppointmentTimesCollectionTVCell()
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
appointmentTimesCollectionTVCell.appointmentTimesToDisplay = self.appointmentTimesToDisplay
appointmentTimesCollectionTVCell.isUserInteractionEnabled = true
//appointmentTimesCollectionTVCell.selectionStyle = .none
return appointmentTimesCollectionTVCell
}
}
The below is the tableview cell that holds the collectionViewCells
class AppointmentTimesCollectionTVCell: UITableViewCell {
var notificationCenter = NotificationCenter.default
let collectionView:UICollectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout.init())
var layout:UICollectionViewFlowLayout = UICollectionViewFlowLayout.init()
let collectionViewCellId = "Cell"
var cellDimensionsArray = [CGSize]()
var appointmentTimes = [Date]()
var indexOfSelectedItem : Int?
var appointmentTimesToDisplay : [Date]{
set(appointmentTimesToSet){ // This method is called whenever appointmentTimesToDisplay is set
appointmentTimes = appointmentTimesToSet
print("appointmentTimesBeingSet: \(appointmentTimes)")
collectionView.reloadData() // This is used to reload images
}
get{
return appointmentTimes
}
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
}
override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
// Configure CollectionView
collectionView.register(ButtonCVCell.self, forCellWithReuseIdentifier: collectionViewCellId)
collectionView.isScrollEnabled = true // To scroll collectionview inside cell
layout.scrollDirection = .horizontal
layout.minimumInteritemSpacing = CGFloat(10.0) // The minimum spacing to use between items in the same row.
layout.minimumLineSpacing = CGFloat(10.0) // The minimum spacing to use between lines of items in the grid.
collectionView.setCollectionViewLayout(layout, animated: true)
collectionView.backgroundColor = Colors.white
collectionView.delegate = self as UICollectionViewDelegate
collectionView.dataSource = self as UICollectionViewDataSource
collectionView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(collectionView)
let viewsDict = [
"collectionView" : collectionView
] as [String : Any]
// collectionView Constraints
contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-5-[collectionView]-5-|", options: [], metrics: nil, views: viewsDict))
contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-5-[collectionView]-5-|", options: [], metrics: nil, views: viewsDict))
}
}
extension AppointmentTimesCollectionTVCell: UICollectionViewDelegateFlowLayout {
// FOR SETTING FIXED SIZES
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// setting the standard widths of 80 and height 30.0 as default to ensure correct collection view cell size
// These have been obtained by printing intrinsicContent size width in function cellforItem at
if cellDimensionsArray.count == 0 { return CGSize(width:80.0, height: 30.0) }
let _cellDimension = cellDimensionsArray[indexPath.item]
return _cellDimension
}
}
extension AppointmentTimesCollectionTVCell: UICollectionViewDataSource {
// MARK: UICollectionViewDataSource
func numberOfSections(in collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return appointmentTimes.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let item = indexPath.item
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: collectionViewCellId, for: indexPath) as? ButtonCVCell
let appointmentTimeObject = appointmentTimes[item]
let appointmentTimeString = " " + DateFormatter().standardDateFormatter.string(from: appointmentTimeObject) + " "
print("indexOfSelectedItem: \(indexOfSelectedItem), item: \(item)")
// This is to ensure that only the selected item color stays and remainder are set to default
if indexOfSelectedItem == item{
cell?.button.backgroundColor = Colors.curieBlue
cell?.button.layer.borderColor = Colors.curieBlue.cgColor
cell?.button.setTitleColor(Colors.white, for: .normal)
} else{
cell?.button.layer.borderWidth = 1
cell?.button.layer.borderColor = Colors.lightGrey.cgColor
cell?.button.backgroundColor = Colors.white
cell?.button.setTitleColor(Colors.curieBlue, for: .normal)
}
cell?.button.tag = item
cell?.button.setTitle(appointmentTimeString , for: .normal)
//cell?.button.addTarget(self, action: #selector(setSelectedTime(sender:)), for: .touchUpInside)
cell?.button.addTarget(self, action: #selector(setSelectedTime(sender:)), for: .touchUpInside)
print("buttonTagSetForTheButton: \(cell)")
if let intrinsicContentSize = cell?.button.intrinsicContentSize {
//let intrinsicContentSize = cell?.button.intrinsicContentSize
let cellWidth = intrinsicContentSize.width
let cellHeight = intrinsicContentSize.height
let cellDimension = CGSize(width: cellWidth, height: cellHeight)
if cellDimensionsArray.count <= appointmentTimes.count{ // Setting dimensions for new cells
cellDimensionsArray.append(cellDimension)
}else{ // Replacing dimensions for existing cells
cellDimensionsArray[item] = cellDimension
}
}
return cell ?? UICollectionViewCell()
//return cell
}
func setSelectedTime(sender: UIButton){
print("setSelectedTimeFuncCalled")
let selectedTime = appointmentTimes[sender.tag]
self.indexOfSelectedItem = sender.tag
let timestamp = selectedTime.timeIntervalSince1970 // Get the Unix timestamp
// Posting a local notification
let selectedAppointmentTimeDict = ["selectedAppointmentTime" : Int(timestamp)]
notificationCenter.post(name: Notification.Name(NotificationNames.appointmentTimeSelected), object: nil, userInfo: selectedAppointmentTimeDict)
self.collectionView.reloadData()
}
}
The below code is used to produce collection view cells with buttons.
class ButtonCVCell: UICollectionViewCell {
let button : UIButton = {
let btn = UIButton(type: .system)
btn.tintColor = Colors.curieBlue
btn.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
btn.layer.cornerRadius = 5
btn.sizeToFit()
return btn
}()
var cellWidthConstraint : NSLayoutConstraint!
var cellWidth : CGFloat{
set(width){
self.cellWidthConstraint.constant = width
self.cellWidthConstraint.isActive = true
print("SettingCellsWidth: \(width)")
}
get{
return self.cellWidthConstraint.constant
}
}
override func awakeFromNib() {
super.awakeFromNib()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
fatalError("init(coder:)")
}
override init(frame: CGRect) {
super.init(frame: frame)
self.contentView.translatesAutoresizingMaskIntoConstraints = false
self.cellWidthConstraint = NSLayoutConstraint(item: contentView, attribute: .width, relatedBy: .equal, toItem: nil, attribute:.notAnAttribute, multiplier: 0, constant: 0.0)
button.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(button)
let viewsDict = [
"button" : button
] as [String : Any]
// Button Constraints
contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[button(30)]|", options: [], metrics: nil, views: viewsDict))
contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[button]", options: [], metrics: nil, views: viewsDict))
}
}
Each collection view cell is button. Use collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) instead
I think the problem is you are trying to use AutoLayout in the CollectionViewCell's ContentView, but CollectionViews use frames.
It is fine if you use AutoLayout for your Button inside the Cell, but the ContentView should resize by itself.
Try removing these lines:
// ButtonCVCell
var cellWidthConstraint : NSLayoutConstraint!
var cellWidth : CGFloat{
set(width){
self.cellWidthConstraint.constant = width
self.cellWidthConstraint.isActive = true
print("SettingCellsWidth: \(width)")
}
get{
return self.cellWidthConstraint.constant
}
}
And these:
// ButtonCVCell override init(frame: CGRect)
self.contentView.translatesAutoresizingMaskIntoConstraints = false
self.cellWidthConstraint = NSLayoutConstraint(item: contentView, attribute: .width, relatedBy: .equal, toItem: nil, attribute:.notAnAttribute, multiplier: 0, constant: 0.0)
I am new to Swift, and I intend to programmatically create a UICollectionView with instances of a subclass of UICollectionViewCell. However, the cells themselves do not show up.
The majority of the following code is derived from this tutorial: iOS Swift: Build UICollectionView programmatically without Storyboards.
This is how I create the UICollectionViewController:
let flowLayout = UICollectionViewFlowLayout()
let productView = ProductView(collectionViewLayout: flowLayout)
productView.setSizeOfCollectionView(width, height: (height * 0.7))
middleLeftView.addSubview(productView.view)
And these are my subclasses:
class ProductView : UICollectionViewController, UICollectionViewDelegateFlowLayout {
let customCellIdentifier = "customCellIdentifier"
var products = [[String]]()
var product1 = ["beer", "2,50"]
var product2 = ["wine", "3,50"]
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.backgroundColor = UIColor.redColor()
collectionView?.delegate = self
collectionView?.dataSource = self
products.append(product1)
products.append(product2)
collectionView?.registerClass(Product.self, forCellWithReuseIdentifier: customCellIdentifier)
self.collectionView?.reloadData()
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let product = collectionView.dequeueReusableCellWithReuseIdentifier(customCellIdentifier, forIndexPath: indexPath) as! Product
product.specifiyProduct(products[indexPath.item])
product.backgroundColor = UIColor.blueColor()
return product
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print(products.count) // prints 2
return products.count
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(300, 300)
}
func setSizeOfCollectionView(width: CGFloat, height: CGFloat){
print(width) // prints 1022.5
print(height) // prints 702.8
collectionView?.frame = CGRectMake(10, 10, (width - 20), (height - 20))
self.collectionView?.reloadData()
}
}
class Product : UICollectionViewCell {
override init(frame: CGRect){
super.init(frame: frame)
self.backgroundColor = UIColor.yellowColor()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func specifiyProduct(info: [String]){
let nameLabel = UILabel(frame: CGRectMake(0, 0, 50, 50))
nameLabel.backgroundColor = UIColor.grayColor()
nameLabel.text = info[0] + info[1]
nameLabel.translatesAutoresizingMaskIntoConstraints = false
addSubview(nameLabel)
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[v0]|" , options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": nameLabel]))
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[v0]|" , options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": nameLabel]))
}
}
The UICollectionView shows up, but the UICollectionViewCells do not. Does anyone know how to fix this?
Try to change
collectionView?.registerClass(Product.self, forCellWithReuseIdentifier: customCellIdentifier)
with
collectionView?.register(Product.self, forCellWithReuseIdentifier: customCellIdentifier)
The method you use to register cell has been renamed to the later one. That's might be the cause.
I have a ViewController Class where I'm putting scrollView and adding stackView as the subview. Now I want to add 'n' number of collectionView inside the stackView. I'm fetching data from server, there will be a different categories. If category A has data, then I need to create one collectionView for that. And I need to handle the data of corresponding collectionView in their class itself.
class ViewController: UIViewController {
var scrollView : UIScrollView!
var stackView : UIStackView!
var responseFullData : JsonFullDataResponse!
var responseData : JsonResponse!
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
print("View Controller init")
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func viewDidAppear(_ animated: Bool) {
print("View did appear")
scrollView.contentSize = CGSize(width: stackView.frame.width, height: stackView.frame.height)
}
override func viewDidLoad() {
super.viewDidLoad()
//loading all the data
loadAllJsonData()
//setting up scroll and stack views
setUpScrollAndStackView()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
print("inside layout")
scrollView.contentSize = CGSize(width: stackView.frame.width, height: stackView.frame.height)
}
func setUpScrollAndStackView() {
scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[scrollView]|", options: .alignAllCenterX, metrics: nil, views: ["scrollView": scrollView]))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[scrollView]|", options: .alignAllCenterX, metrics: nil, views: ["scrollView": scrollView]))
stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.spacing = 20.0
stackView.axis = .vertical
scrollView.addSubview(stackView)
scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[stackView]|", options: NSLayoutFormatOptions.alignAllCenterX, metrics: nil, views: ["stackView": stackView]))
scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[stackView]", options: NSLayoutFormatOptions.alignAllCenterX, metrics: nil, views: ["stackView": stackView]))
setUpOtherViewsInStack()
}
func setUpOtherViewsInStack() {
if responseFullData.banner?.count != 0 {
print("banner has data")
var bannerCollection : BannerCollectionView = BannerCollectionView() as! BannerCollectionView
bannerCollection.register(UINib.init(nibName: "BannerCell", bundle: nil), forCellWithReuseIdentifier: "BannerCell")
stackView.addArrangedSubview(bannerCollection)
}
}
BannerCollectionView Code
class BannerCollectionView: UICollectionView , UICollectionViewDataSource{
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int{
print("control is in datasource")
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BannerCell", for: indexPath) as! BannerCell
cell.backgroundColor = UIColor.blue
return cell
}
}
How do I make this work. In which class and where I should set the delegate and datasource property of BannerCollectionView? How do I initialise this?
As I understand you need to make a for from 0 to count in responseFullData.banner.count adding a collectionView each time
if let count = responseFullData.banner?.count {
for i in 0..<count {
var bannerCollection : BannerCollectionView = BannerCollectionView() as! BannerCollectionView
bannerCollection.register(UINib.init(nibName: "BannerCell", bundle: nil), forCellWithReuseIdentifier: "BannerCell")
stackView.addArrangedSubview(bannerCollection)
}
}
I have added 3 collectionView inside the UIStackView(Vertical stack). The whole view can be scrolled vertically and the collection items can be scrolled either horizontally or vertically.
class HomePageViewController: UIViewController,HeaderViewDelegate {
var scrollView : UIScrollView!
var stackView : UIStackView!
var responseFullData : JsonFullDataResponse!
if responseFullData?.menu?.count != nil{
print("menu has data")
var menuCollection : MenuCollectionView = MenuCollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout.init())
menuCollection.backgroundColor = .white
menuCollection.menuData = (self.responseFullData.menu)!
menuCollection.dataSource = menuCollection.self
menuCollection.delegate = menuCollection.self
createCollectionViews(collectionViewClass: menuCollection, identifier: "MenuCell",height : 175)
}
if responseFullData?.hongbei?.count != nil {
print("hongbei has data")
var hongbeiCollection : HongbeiCollectionView = HongbeiCollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout.init())
hongbeiCollection.dataSource = hongbeiCollection
hongbeiCollection.delegate = hongbeiCollection
hongbeiCollection.allowsSelection = true
hongbeiCollection.backgroundColor = .white
hongbeiCollection.hongbeiData = (self.responseFullData.hongbei)!
addHeaderView(headerTitle : "Hongbei")
createCollectionViews(collectionViewClass: hongbeiCollection, identifier: "HongbeiCell",height : 150)
}
if responseFullData?.freeZone?.count != nil {
print("freezone has data")
var freezoneCollection : FreeZoneCollectionView = FreeZoneCollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout.init())
freezoneCollection.dataSource = freezoneCollection.self
freezoneCollection.delegate = freezoneCollection.self
freezoneCollection.backgroundColor = .white
freezoneCollection.freeZoneData = (self.responseFullData.freeZone)!
addHeaderView(headerTitle : "FreeZone")
createCollectionViews(collectionViewClass: freezoneCollection, identifier: "FreeZoneCell",height : 150)
}
func createCollectionViews(collectionViewClass : UICollectionView, identifier : String,height : CGFloat ){
collectionViewClass.widthAnchor.constraint(equalToConstant: self.view.frame.width).isActive = true
collectionViewClass.heightAnchor.constraint(equalToConstant: height).isActive = true
collectionViewClass.register(UINib.init(nibName: identifier, bundle: nil), forCellWithReuseIdentifier: identifier)
collectionViewClass.showsHorizontalScrollIndicator = false
collectionViewClass.showsVerticalScrollIndicator = false
stackView.addArrangedSubview(collectionViewClass)
}
func addHeaderView(headerTitle : String){
let headerView = HeaderView.instanceFromNib() as! HeaderView
headerView.widthAnchor.constraint(equalToConstant: self.view.frame.width).isActive = true
headerView.heightAnchor.constraint(equalToConstant: 20).isActive = true
headerView.headerLabel.text = headerTitle
headerView.frame = headerView.frame.offsetBy(dx: 20, dy: 0)
headerView.delegate = self
stackView.addArrangedSubview(headerView)
}
}
class MenuCollectionView: UICollectionView,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {
var menuData : [MenuData]!
override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
super.init(frame: frame, collectionViewLayout: layout)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int{
print("Menu")
return menuData.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MenuCell", for: indexPath) as! MenuCell
cell.menuLabel.text = menuData[indexPath.item].title!
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{
return CGSize(width: (collectionView.frame.width * 0.175), height: 75)
}
I have a separate class for each collectionView in the stack, where I handle the data source and delegate methods. So I can have any number for collection items I want in each collectionView.
I wrote the code for collectionView infinite scroll with json parse. Next want to view 20 data each time. After print 20data i will show footer.
Now it is going to view all data in a time. Json parse is ok, also footer view is ok. But the problem is infinite-scroll is not working at all.
Here is my all code:
import Foundation
import UIKit
enum LoadMoreStatus{
case loading
case finished
case haveMore
}
class Product: NSObject {
var id: Int?
var category_id: Int?
var image: String?
var name: String?
var ar_name: String?
var ar_description: String?
var price: NSNumber?
var quantity: String?
var is_featured: String?
var seller_id: String?
var payment_required: String?
var is_editors_choice: String?
var created_at: String?
var updated_at: String?
}
let categoryCellid = "categoryCellid"
class ProductByCategoryCollectionView: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var headercellId = "headercellId"
var footerCellid = "firstfootercellid"
var numberOfCells = 5
var loadingStatus = LoadMoreStatus.haveMore
var arrProduct = [Product]()
var category_id:Int = 0;
var product_count:Int = 0;
func reloadData(){
collectionView?.reloadData()
if numberOfCells > 0 {
collectionView?.scrollToItem(at: IndexPath(row: 0, section: 0), at: .left, animated: true)
}
}
func loadMore() {
if numberOfCells >= arrProduct.count{ // here will show untill 22
loadingStatus = .finished
collectionView?.reloadData()
return
}
Timer.schedule(delay: 2) { timer in
self.numberOfCells += 10
self.collectionView?.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.getPropductListByCategory()
collectionView?.backgroundColor = .white
navigationItem.title = "Product"
navigationItem.backBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: nil, action: nil)
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Sort By", style: .plain, target: nil, action: nil)
self.setupHeaderView()
collectionView?.register(ProductByCategoryCollectionViewCell.self, forCellWithReuseIdentifier: categoryCellid)
collectionView?.register(ProductByCategoryFooterCell.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: footerCellid)
}
override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
var text=""
switch UIDevice.current.orientation{
case .portrait:
text="Portrait"
case .portraitUpsideDown:
text="PortraitUpsideDown"
case .landscapeLeft:
text="LandscapeLeft"
case .landscapeRight:
text="LandscapeRight"
default:
text="Another"
}
NSLog("You have moved: \(text)")
collectionView?.reloadData()
}
func showCategoryDetailSegue() {
let detailcontroller = UIViewController()
navigationController?.pushViewController(detailcontroller, animated: true)
}
func sortBtnTarget() {
}
func filterBtnTarget() {
}
let dividedLine: UIView = {
let view = UIView()
view.backgroundColor = UIColor(white: 0.4, alpha: 0.4)
return view
}()
let totalItemLabel: UILabel = {
let label = UILabel()
label.text = ""
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 15)
label.backgroundColor = UIColor.white
return label
}()
let dividerLineView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.white
return view
}()
func setupHeaderView(){
view.backgroundColor = UIColor(white: 0.4, alpha: 0.4)
dividedLine.frame = CGRect(x: 0, y: 95, width: view.frame.width, height: 1)
totalItemLabel.frame = CGRect(x: 0, y: 55, width: view.frame.width, height: 40)
view.addSubview(totalItemLabel)
view.addSubview(dividedLine)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return arrProduct.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if(indexPath.row==arrProduct.count-1){
if loadingStatus == .haveMore {
self.perform(#selector(ProductByCategoryCollectionView.loadMore), with: nil, afterDelay: 0)
}
}
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: categoryCellid, for: indexPath) as! ProductByCategoryCollectionViewCell
cell.callProductObject4Cell = arrProduct[indexPath.item]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 172, height: 300)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(32, 10, 0, 10)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let controller1 = UICollectionViewController(collectionViewLayout: layout)
navigationController?.pushViewController(controller1, animated: true)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
collectionView?.collectionViewLayout.invalidateLayout()
}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
var footerView:ProductByCategoryFooterCell!
if (kind == UICollectionElementKindSectionFooter) && (loadingStatus != .finished){
footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: footerCellid, for: indexPath) as! ProductByCategoryFooterCell
}
return footerView
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
return (loadingStatus == .finished) ? CGSize.zero : CGSize(width: self.view.frame.width, height: 50)
}
}
class ProductByCategoryCollectionViewCell: UICollectionViewCell {
var callProductObject4Cell: Product?{
didSet {
productLabel.text = callProductObject4Cell?.name
if let price = callProductObject4Cell?.price {
//priceLabel.text = "$\(price)"
priceLabel.text = "\(price) TK"
} else {
priceLabel.text = ""
}
if let profileImageUrl = callProductObject4Cell?.image {
productImage.loadImageUsingUrlString(profileImageUrl)
}
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setupcategoryCell()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let productImage: UIImageView = {
let image = UIImageView()
image.image = UIImage(named: "default")
image.contentMode = .scaleAspectFit
image.layer.borderWidth = 1
image.layer.borderColor = UIColor.orange.cgColor
image.layer.masksToBounds = true
return image
}()
let productLabel: UILabel = {
let label = UILabel()
label.text = "productName"
label.textColor = .black
label.numberOfLines = 0
label.font = UIFont.boldSystemFont(ofSize: 10)
return label
}()
let priceLabel: UILabel = {
let label = UILabel()
// label.backgroundColor = .lightGray
label.text = ""
label.textColor = .orange
label.font = UIFont.systemFont(ofSize: 13)
return label
}()
func setupcategoryCell() {
addSubview(productImage)
addSubview(productLabel)
addSubview(priceLabel)
addConstraintsWithFormat("H:|[v0]|", views: productImage)
addConstraintsWithFormat("V:|[v0(230)]-2-[v1][v2(10)]-5-|", views: productImage,productLabel, priceLabel)
addConstraintsWithFormat("H:|[v0]|", views: productLabel)
addConstraintsWithFormat("H:|[v0]|", views: priceLabel)
}
}
class ProductByCategoryFooterCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .white
setupCell()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let menuHeaderLabel: UILabel = {
let label = UILabel()
label.text = "loadin more waiting"
label.textColor = .green
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 15)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
func setupCell() {
addSubview(menuHeaderLabel)
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-8-[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": menuHeaderLabel]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-5-[v0(30)]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": menuHeaderLabel]))
}
}
extension Timer {
class func schedule(delay: TimeInterval, handler: #escaping (Timer!) -> Void) -> Timer {
let fireDate = delay + CFAbsoluteTimeGetCurrent()
let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, 0, 0, 0, handler)
CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.commonModes)
return timer!
}
class func schedule(repeatInterval interval: TimeInterval, handler: #escaping (Timer!) -> Void) -> Timer {
let fireDate = interval + CFAbsoluteTimeGetCurrent()
let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, interval, 0, 0, handler)
CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.commonModes)
return timer!
}
}
enum LoadMoreStatus {
case loading
case finished
case haveMore
}
class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var verticalDataSource = [String]()
var firstCellid = "firstcellid"
var firstFooterCellid = "firstfootercellid"
var numberOfCells = 5
var loadingStatus = LoadMoreStatus.haveMore
func reloadData() {
//numberOfCells = 10
collectionView?.reloadData()
if numberOfCells > 0 {
collectionView?.scrollToItem(at: IndexPath(row: 0, section: 0), at: .left, animated: true)
}
}
func loadMore() {
if numberOfCells >= 40 {
// here will show untill finished number
loadingStatus = .finished
collectionView?.reloadData()
return
}
// Replace code with web service and append to data source
Timer.schedule(delay: 2) { timer in
self.numberOfCells += 2
self.collectionView?.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.automaticallyAdjustsScrollViewInsets = false
collectionView?.register(VerticalCollectionViewCell.self, forCellWithReuseIdentifier: firstCellid)
collectionView?.register(VerticalCollectionViewCell2.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: firstFooterCellid)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK - Rotation methods
override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
var text=""
switch UIDevice.current.orientation {
case .portrait:
text="Portrait"
case .portraitUpsideDown:
text="PortraitUpsideDown"
case .landscapeLeft:
text="LandscapeLeft"
case .landscapeRight:
text="LandscapeRight"
default:
text="Another"
}
NSLog("You have moved: \(text)")
collectionView?.reloadData()
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numberOfCells
}
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if(indexPath.row==numberOfCells-1) {
if loadingStatus == .haveMore {
self.perform(#selector(ViewController.loadMore), with: nil, afterDelay: 0)
}
}
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: firstCellid, for: indexPath) as! VerticalCollectionViewCell
cell.menuHeaderLabel.text = "Labet text no \(indexPath.item)"
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: self.view.frame.width, height: 100)
}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
var footerView:VerticalCollectionViewCell2!
if (kind == UICollectionElementKindSectionFooter) && (loadingStatus != .finished) {
footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: firstFooterCellid, for: indexPath) as! VerticalCollectionViewCell2
}
return footerView
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
return (loadingStatus == .finished) ? CGSize.zero : CGSize(width: self.view.frame.width, height: 50)
}
}
class VerticalCollectionViewCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupCell()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let menuHeaderLabel: UILabel = {
let label = UILabel()
label.text = "lable text"
label.textColor = .orange
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 15)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
func setupCell() {
addSubview(menuHeaderLabel)
// addTaskButton.addTarget(self, action: #selector(MenuHeader.addTask), for: .touchUpInside)
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-8-[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": menuHeaderLabel]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-5-[v0(30)]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": menuHeaderLabel]))
}
}
i want to infinite scrolling 10 images in collectionView programmatically of swift. the image came from web by json according to my choice. i have been unable to scrolling 20 image in a times.
here is my code
import Foundation
import UIKit
let categoryCellid = "categoryCellid"
class ProductByCategoryCollectionView: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var headercellId = "headercellId"
var callCategoryObject = [Product]()
func getPropductListByCategory(){
// has api code, that was well
}
override func viewDidLoad() {
super.viewDidLoad()
self.getPropductListByCategory()
collectionView?.backgroundColor = .white
navigationItem.title = "Product"
navigationItem.backBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: nil, action: nil)
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Sort By", style: .plain, target: nil, action: nil)
self.setupHeaderView()
collectionView?.register(ProductByCategoryCollectionViewCell.self, forCellWithReuseIdentifier: categoryCellid)
}
func showCategoryDetailSegue() {
let detailcontroller = UIViewController()
navigationController?.pushViewController(detailcontroller, animated: true)
}
func sortBtnTarget() {
}
func filterBtnTarget() {
}
let dividedLine: UIView = {
let view = UIView()
view.backgroundColor = UIColor(white: 0.4, alpha: 0.4)
return view
}()
let totalItemLabel: UILabel = {
let label = UILabel()
label.text = ""
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 15)
label.backgroundColor = UIColor.white
return label
}()
let dividerLineView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.white
return view
}()
func setupHeaderView(){
view.backgroundColor = UIColor(white: 0.4, alpha: 0.4)
dividedLine.frame = CGRect(x: 0, y: 95, width: view.frame.width, height: 1)
totalItemLabel.frame = CGRect(x: 0, y: 55, width: view.frame.width, height: 40)
view.addSubview(totalItemLabel)
view.addSubview(dividedLine)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return callCategoryObject.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: categoryCellid, for: indexPath) as! ProductByCategoryCollectionViewCell
cell.callProductObject4Cell = callCategoryObject[indexPath.item]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 172, height: 300)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(32, 10, 0, 10)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let controller1 = DetailsController(collectionViewLayout: layout)
navigationController?.pushViewController(controller1, animated: true)
}
}
class ProductByCategoryCollectionViewCell: UICollectionViewCell {
var callProductObject4Cell: Product? {
didSet {
productLabel.text = callProductObject4Cell?.name
// priceLabel.text = String(describing: callProductObject4Cell?.price)
if let price = callProductObject4Cell?.price {
priceLabel.text = "$\(price)"
} else {
priceLabel.text = ""
}
if let profileImageUrl = callProductObject4Cell?.image {
productImage.loadImageUsingUrlString(profileImageUrl)
}
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setupcategoryCell()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let productImage: UIImageView = {
let image = UIImageView()
image.image = UIImage(named: "default")
image.contentMode = .scaleAspectFit
image.layer.borderWidth = 1
image.layer.borderColor = UIColor.orange.cgColor
image.layer.masksToBounds = true
return image
}()
let productLabel: UILabel = {
let label = UILabel()
label.text = "productName"
label.textColor = .black
label.numberOfLines = 0
label.font = UIFont.boldSystemFont(ofSize: 10)
return label
}()
let priceLabel: UILabel = {
let label = UILabel()
// label.backgroundColor = .lightGray
label.text = ""
label.textColor = .orange
label.font = UIFont.systemFont(ofSize: 13)
return label
}()
func setupcategoryCell() {
addSubview(productImage)
addSubview(productLabel)
addSubview(priceLabel)
addConstraintsWithFormat("H:|[v0]|", views: productImage)
addConstraintsWithFormat("V:|[v0(230)]-2-[v1][v2(10)]-5-|", views: productImage,productLabel, priceLabel)
addConstraintsWithFormat("H:|[v0]|", views: productLabel)
addConstraintsWithFormat("H:|[v0]|", views: priceLabel)
}
}
Use this code for an infinite UIScrollView:
import Foundation
import UIKit
enum LoadMoreStatus {
case loading
case finished
case haveMore
}
class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var verticalDataSource = [String]()
var firstCellid = "firstcellid"
var firstFooterCellid = "firstfootercellid"
var numberOfCells = 5
var loadingStatus = LoadMoreStatus.haveMore
func reloadData() {
//numberOfCells = 10
collectionView?.reloadData()
if numberOfCells > 0 {
collectionView?.scrollToItem(at: IndexPath(row: 0, section: 0), at: .left, animated: true)
}
}
func loadMore() {
if numberOfCells >= 40 {
// here will show untill finished number
loadingStatus = .finished
collectionView?.reloadData()
return
}
// Replace code with web service and append to data source
Timer.schedule(delay: 2) { timer in
self.numberOfCells += 2
self.collectionView?.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.automaticallyAdjustsScrollViewInsets = false
collectionView?.register(VerticalCollectionViewCell.self, forCellWithReuseIdentifier: firstCellid)
collectionView?.register(VerticalCollectionViewCell2.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: firstFooterCellid)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK - Rotation methods
override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
var text=""
switch UIDevice.current.orientation {
case .portrait:
text="Portrait"
case .portraitUpsideDown:
text="PortraitUpsideDown"
case .landscapeLeft:
text="LandscapeLeft"
case .landscapeRight:
text="LandscapeRight"
default:
text="Another"
}
NSLog("You have moved: \(text)")
collectionView?.reloadData()
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numberOfCells
}
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if(indexPath.row==numberOfCells-1) {
if loadingStatus == .haveMore {
self.perform(#selector(ViewController.loadMore), with: nil, afterDelay: 0)
}
}
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: firstCellid, for: indexPath) as! VerticalCollectionViewCell
cell.menuHeaderLabel.text = "Labet text no \(indexPath.item)"
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: self.view.frame.width, height: 100)
}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
var footerView:VerticalCollectionViewCell2!
if (kind == UICollectionElementKindSectionFooter) && (loadingStatus != .finished) {
footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: firstFooterCellid, for: indexPath) as! VerticalCollectionViewCell2
}
return footerView
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
return (loadingStatus == .finished) ? CGSize.zero : CGSize(width: self.view.frame.width, height: 50)
}
}
class VerticalCollectionViewCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupCell()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let menuHeaderLabel: UILabel = {
let label = UILabel()
label.text = "lable text"
label.textColor = .orange
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 15)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
func setupCell() {
addSubview(menuHeaderLabel)
// addTaskButton.addTarget(self, action: #selector(MenuHeader.addTask), for: .touchUpInside)
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-8-[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": menuHeaderLabel]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-5-[v0(30)]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": menuHeaderLabel]))
}
}
class VerticalCollectionViewCell2: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .white
setupCell()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let menuHeaderLabel: UILabel = {
let label = UILabel()
label.text = "loadin more waiting"
label.textColor = .green
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 15)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
func setupCell() {
addSubview(menuHeaderLabel)
// addTaskButton.addTarget(self, action: #selector(MenuHeader.addTask), for: .touchUpInside)
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-8-[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": menuHeaderLabel]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-5-[v0(30)]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": menuHeaderLabel]))
}
}
extension Timer {
class func schedule(delay: TimeInterval, handler: #escaping (Timer!) -> Void) -> Timer {
let fireDate = delay + CFAbsoluteTimeGetCurrent()
let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, 0, 0, 0, handler)
CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.commonModes)
return timer!
}
class func schedule(repeatInterval interval: TimeInterval, handler: #escaping (Timer!) -> Void) -> Timer {
let fireDate = interval + CFAbsoluteTimeGetCurrent()
let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, interval, 0, 0, handler)
CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.commonModes)
return timer!
}
}