Could not dequeue a view of kind: UICollectionElementKindCell - ios

I need a little help. I'm trying to create UICollectionView with header section, using custom layout for UICollectionViewCell(item) and UICollectionReusableView(header). Before header, everything was working perfectly, but now for some reason I'm always getting this error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason:
'could not dequeue a view of
kind: UICollectionElementKindCell with identifier ProductCellView - must register
a nib or a class for the identifier or connect a prototype cell in a storyboard'
I have registered both files in CollectionView. Here is my code:
override func viewDidLoad() {
super.viewDidLoad()
productsCollectionView.delegate = self
productsCollectionView.dataSource = self
productsCollectionView.register(UINib(nibName: "SectionHeader", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "CollectionReusableView");
productsCollectionView.register(UINib(nibName: "HomeProductViewCell", bundle: nil), forCellWithReuseIdentifier: "ProductCellView")
}
And I will post now one block of code which is used for handling view of header section and which is causing crash. If I comment that part of code, collection view will show regular items without header of course. Here it is:
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
//1
switch kind {
//2
case UICollectionElementKindSectionHeader:
//3
if let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "CollectionReusableView", for: indexPath) as? SectionHeader{
sectionHeader.categoriesCollectionView.register(UINib(nibName: "CategoryViewCell", bundle: nil), forCellWithReuseIdentifier: "CategoryViewCell")
sectionHeader.homeImagesCollectionView.register(UINib(nibName: "HomeImageViewCell", bundle: nil), forCellWithReuseIdentifier: "HomeImageViewCell")
sectionHeader.homeImagesCollectionView.delegate = self
sectionHeader.homeImagesCollectionView.dataSource = self
sectionHeader.categoriesCollectionView.delegate = self
sectionHeader.categoriesCollectionView.dataSource = self
// Add icon to button
let icon = UIImage(named: "magnifying-glass")!
sectionHeader.btnSearch.setImage(icon, for: .normal)
sectionHeader.btnSearch.imageEdgeInsets = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 20)
sectionHeader.btnSearch.titleEdgeInsets = UIEdgeInsets(top: 0, left: 30, bottom: 0, right: 0)
sectionHeader.btnSearch.imageView?.contentMode = .scaleAspectFit
sectionHeader.btnSearch.layer.cornerRadius = 4
sectionHeader.prepareCategories()
sectionHeader.prepareHomeImages()
return sectionHeader
}
default:
//4
assert(false, "Unexpected element kind")
}
return UICollectionReusableView()
}
So I'm really desperate here because I have lost almost two days finding bug why this is happening. I would really appreciate if someone point me in the right direction where to look for bug, because I have tried almost everything I knew.

The problem is in the inner collections since you set the delegate & dataSource here
sectionHeader.homeImagesCollectionView.delegate = self
sectionHeader.homeImagesCollectionView.dataSource = self
sectionHeader.categoriesCollectionView.delegate = self
sectionHeader.categoriesCollectionView.dataSource = self
it asks for
if let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "CollectionReusableView", for: indexPath) as? SectionHeader{
so you have to wrap the whole part inside the type of the collection
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if collectionView == mainCollection {
}
else
if collectionView == homeImagesCollectionView {
}
else { // categoriesCollectionView
}
}
BTW register should be inside viewDidLoad for a collection inside a VC , and in init/awakeFromnib inside a collectionCell custom class

I experienced a similar problem when I was fetching my data and reloading the tableview before registering the nibs. This is my best answer given the info you supplied.

Related

Unable to Dequeue Registered CollectionViewCells

Searched here and there but I couldn't find anything that I haven't already tried to fix my issue, so going to ask it again.
I am trying to use a collection view with custom cells.
The main collection view is in the Main View Controller.
I'm using a generic cell named GenericHomeCollectionViewCell, then customize another collection view that it has. This cell doesn't have any issue with registering and dequeuing. (It might sound weird but I already have an application with this usage and it works without any problem, so I wanted to use the same method again.)
The crash happens when I try to register and dequeue cells inside that generic cell.
I have 4 different custom cells for use which are registered in awakeFromNib().
GenericHomeCollectionViewCell.swift
override func awakeFromNib() {
super.awakeFromNib()
newsCollectionView.register(UINib(nibName: "HeadlineNewsCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "HeadlineNewsCollectionViewCell")
newsCollectionView.register(UINib(nibName: "HomeAuthorCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "HomeAuthorCollectionViewCell")
newsCollectionView.register(UINib(nibName: "NewsListCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "NewsListCollectionViewCell")
newsCollectionView.register(UINib(nibName: "HomeDetailedNewCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "HomeDetailedNewCollectionViewCell")
newsCollectionView.delegate = self
newsCollectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if sectionType == .swipe {
let cell : HeadlineNewsCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "HeadlineNewsCollectionViewCell", for: indexPath) as! HeadlineNewsCollectionViewCell
cell.prepareCell(news: newsList[indexPath.row])
return cell
} else if sectionType == .homeAuthor {
let cell : HomeAuthorCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeAuthorCollectionViewCell", for: indexPath) as! HomeAuthorCollectionViewCell
cell.prepareCell(news: newsList[indexPath.row])
return cell
} else {
let cell : HeadlineNewsCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "HeadlineNewsCollectionViewCell", for: indexPath) as! HeadlineNewsCollectionViewCell
cell.prepareCell(news: newsList[indexPath.row])
return cell
}
}
When I launch the application, I get crash with error:
*** Assertion failure in -[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:], UICollectionView.m:6502
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'could not dequeue a view of kind: UICollectionElementKindCell with identifier HeadlineNewsCollectionViewCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
I tried to give a reuse identifier name from the storyboard editor's but there is no difference.

Error When Registering Header in UICollectionViewCell iOS Swift 4

I'm doing Let's Built That App's twitter remake tutorial and I keep coming across this error: 'could not dequeue a view of kind: UICollectionElementKindSectionFooter with identifier headerId - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'. I try to register the header below but my app still gives me the same error. This is the link to the video:
https://www.youtube.com/watch?v=2fcf9yFe944&list=PL0dzCUj1L5JE1wErjzEyVqlvx92VN3DL5
let cellId = "cellId"
let headerId = "headerId"
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.backgroundColor = .white
collectionView?.register(WordCell.self, forCellWithReuseIdentifier: cellId)
collectionView?.register(UICollectionViewCell.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: headerId)
}
You registered that view as UICollectionElementKindSectionHeader but are trying to use it as UICollectionElementKindSectionFooter. These details are key.
You can check to make sure the collectionView method is getting the correct type by doing something like this:
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionElementKindSectionHeader {
//Now you can dequeue your view with reuseId "headerId"
} else {
//This is where you set the footerView, if you are using one
}

UICollectionView.dequeueReusableCell crashes

In viewDidLoad I register the cell like this:
let cellIdentifier = "Cell"
override func viewDidLoad() {
super.viewDidLoad()
let cellNib = UINib(nibName: "ViewCell", bundle: nil)
collection.register(cellNib, forCellWithReuseIdentifier: cellIdentifier)
}
and in cellForItemAt of the UICollectionViewDataSource I do:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// It crashes while trying to dequeue with the Error message: Assertion failure in -[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:]
let dequedCell = collection.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath)
return dequedCell
}
The onlystrange thing might be that the code is Mixed Swift/ObjC, and ViewCell is ObjC and gets imported in the bridging header:
#import "ViewCell.h"
I am getting the following error:
*** Assertion failure in -[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewC‌​ategory:],
/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UI‌​Kit-3600.7.47/UIColl‌​ectionView.m:5106
I made sure all names are correct. Does anyone know why this crash is happening??
Here is problem
1) You need to register cell identifier in XIB,
2) Assign Class name to XIB
3) cell for row you need to check with as? YourClass in dequeue and
4) dequeue with same identifier you assign to XIB and register
Set collectionview cell identifier as Cell in storyboard.
Does anyone know why this crash is happening?
One thing to consider is that the docs for register(_:forCellWithReuseIdentifier:) say:
The nib file must contain only one top-level object and that object must be of the type UICollectionViewCell.
So, check that that's true. In other words...
let nibObjects = cellNib.instantiate(withOwner: nib, options: nil)
let count = nibObjects.count // is this 1?
let view = nibObjects.first // is view a UICollectionViewCell?

Error implementing a 2nd UICollectionView: could not dequeue a view of kind: UICollectionElementKindCell with identifier xxxx - must register

This question is a follow-up to this previous question.
I've implemented one UICollectionView, but can't get the project to run when I implement a second one. Where things are dying is at the line in
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
where I first start to set up the prototype cell. I have a left and a right collection view, with the cell in each named cellLeft and cellRight respectively, and those names stored in constants reuseIdentifierLeft and reuseIdentifierRight. (No extra space in the constants -- common issue in other answers, checked for that.) The statement where things crash is
let rightCell = collectionView.dequeueReusableCell(withReuseIdentifier:
reuseIdentifierRight, for: indexPath as IndexPath) as!
MyRightCollectionViewCell
The error message is
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'could not dequeue a view of kind: UICollectionElementKindCell with identifier cellRight - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
The obvious point of failure is not having correctly registered the cell and/or the label, although I've been through every possibility for doing that I can think of, and nothing seems to help. (The collection view on the left side was working fine when it was the only CollectionView in the project, so I thought I knew how to hook things up correctly. But when things initialize, the right side is getting initialized first, so I can't tell if the left side would fail like this one is, or not.)
I've spent literally hours checking that things are hooked up, and as best I can tell, they are. Take this out, put it back together, make sure it's all there, run it again, same crash.
Screenshots of my work:
Code:
ViewController.swift
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var collectionViewLeft: UICollectionView!
var collectionViewRight: UICollectionView!
let collectionViewLeftIdentifier = "CollectionViewLeftCell"
let collectionViewRightIdentifier = "CollectionViewRightCell"
override func viewDidLoad() {
super.viewDidLoad()
let layoutLeft = UICollectionViewFlowLayout()
layoutLeft.itemSize = CGSize(width: 100, height: 100)
let layoutRight = UICollectionViewFlowLayout()
layoutRight.itemSize = CGSize(width: 100, height: 100)
collectionViewLeft = UICollectionView(frame: self.view.frame, collectionViewLayout: layoutLeft)
collectionViewRight = UICollectionView(frame: self.view.frame, collectionViewLayout: layoutRight)
collectionViewLeft.delegate = self
collectionViewRight.delegate = self
collectionViewLeft.dataSource = self
collectionViewRight.dataSource = self
collectionViewLeft.register(UICollectionViewCell.self, forCellWithReuseIdentifier: collectionViewLeftIdentifier)
collectionViewRight.register(UICollectionViewCell.self, forCellWithReuseIdentifier: collectionViewRightIdentifier)
self.view.addSubview(collectionViewLeft)
self.view.addSubview(collectionViewRight)
print("Both subviews added ok.") // this DOES print.
}
let reuseIdentifierLeft = "cellLeft"
let reuseIdentifierRight = "cellRight"
var itemsRight = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48"]
var itemsLeft = ["10", "20", "30", "40", "50", "60"]
// MARK: - UICollectionViewDataSource protocol
// tell the collection view how many cells to make
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == self.collectionViewLeft {
return self.itemsLeft.count
} else if collectionView == self.collectionViewRight {
return self.itemsRight.count
} else {
print("This is very bad")
assert(false, "Passed collectionView is neither collectionViewLeft nor collectionViewRight -- ruh roh!")
return 0
}
}
// make a cell for each cell index path
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == self.collectionViewLeft {
print("Attempting Left...") // not observed -- 'right' is evidently getting called first.
// get a reference to our storyboard cell
let leftCell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifierLeft, for: indexPath as IndexPath) as! MyCollectionViewCell
print("hit let leftCell = collectionView.dequeue...")
leftCell.myLeftLabel.text = self.itemsLeft[indexPath.item]
leftCell.backgroundColor = UIColor.red // make cell more visible in our example project
return leftCell
} else if collectionView == self.collectionViewRight {
print("Attempting Right... reuseIdentifierRight='" + reuseIdentifierRight + "'") // this prints: "Attempting Right... reuseIdentifierRight='cellRight'" which looks okay.
let rightCell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifierRight, for: indexPath as IndexPath) as! MyRightCollectionViewCell
// ^
// /|\
// / | \
// |
// |
//
// Dies here.
// *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'could not dequeue a view of kind: UICollectionElementKindCell with identifier cellRight - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
// attempted, no help:
// let rightCell = collectionView.dequeueReusableCell(withReuseIdentifier: self.reuseIdentifierRight, for: indexPath as IndexPath) as! MyRightCollectionViewCell
// i.e. adding "self" into "self.reuseIdentifierRight"
print("Successfully hit 'let rightCell = collectionView.dequeue...'") // does NOT print.
// Use the outlet in our custom class to get a reference to the UILabel in the cell
rightCell.myRightLabel.text = self.itemsRight[indexPath.item]
rightCell.backgroundColor = UIColor.green
return rightCell
} else {
print("This is very bad")
assert(false, "Passed collectionView is neither collectionViewLeft nor collectionViewRight -- ruh roh!")
// won't actually execute the following, but to keep the compiler happy...
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifierLeft, for: indexPath as IndexPath) as! MyCollectionViewCell
return cell
}
}
// MARK: - UICollectionViewDelegate protocol
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// handle tap events
if collectionView == self.collectionViewLeft {
print("You tapped cell #\(indexPath.item) on the LEFT!")
} else if collectionView == self.collectionViewRight {
print("You tapped cell #\(indexPath.item) on the RIGHT!")
} else {
print("This is very bad")
assert(false, "Passed collectionView is neither collectionViewLeft nor collectionViewRight -- ruh roh!")
}
}
}
MyCollectionViewCell.swift
import UIKit
class MyCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var myLeftLabel: UILabel!
}
MyRightCollectionViewCell.swift
import UIKit
class MyRightCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var myRightLabel: UILabel!
}
I am absolutely at wit's end here, having looked through various Stack Exchange articles & having tried everything in them I can find, but nothing seems to change what's crashing. Am I missing something simple & obvious about how the cell and/or label need to be hooked up to each other? Thanks for any help that can be offered -- it will be most greatly appreciated!
Get rid of
let reuseIdentifierLeft = "cellLeft"
let reuseIdentifierRight = "cellRight"
and change your dequeue to
let rightCell = collectionView.dequeueReusableCell(withReuseIdentifier: collectionViewRightIdentifier, for: indexPath as IndexPath) as! MyRightCollectionViewCell
For both the left and right collection view
The identifier you register in collectionViewRight.register(UICollectionViewCell.self, forCellWithReuseIdentifier: collectionViewRightIdentifier) is the reuseIdentifier, and shouldnt be a separate identifier
also change the class that is being registered for each cell to the appropriate ones, eg
collectionViewLeft.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: collectionViewLeftIdentifier)
collectionViewRight.register(MyRightCollectionViewCell.self, forCellWithReuseIdentifier: collectionViewRightIdentifier)
Is there a reason you're using 2 sets of reuse identifiers? Are collectionViewLeftIdentifier and reuseIdentifierLeft meant to be the same thing?
You're registering your cell with collectionViewLeftIdentifier but you are dequeuing with reuseIdentifierLeft. It seems a little bit confusing.
Judging by your screenshot, it looks like your identifier should be cellLeft, which should be under reuseIdentifierLeft.

Custom UICollectionViewLayout and floating supplementary header views crash

I am trying to create a UICollectionView which represents a grid and I would like to create a ruler (floating header view) at the top edge which floats along in the y-axis.
So, much like in UITableViews, this view should basically just scroll with the content at the top of the screen. I hope that description makes it clear enough. So much for theory, let's get to the practical part!
Here is what I am working with now:
I registered the class GridRulerView which is a subclass of
UICollectionReusableView with the collection view.
I return the correct Size for the supplementary view for the right kind and CGSizeZero where there is no header.
I implemented viewForSupplementaryElementOfKind::
func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView
{
var reusableHeaderView : UICollectionReusableView!
if kind == GridRulerView.Kind{
reusableHeaderView = collectionView.dequeueReusableSupplementaryViewOfKind(GridRulerView.Kind, withReuseIdentifier: GridRulerView.Kind, forIndexPath: indexPath) as! UICollectionReusableView
}
return reusableHeaderView
}
I have a custom UICollectionViewLayout with the following
layoutAttributesForElementsInRect: method:
override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? {
var attribs = [UICollectionViewLayoutAttributes]()
for (indexPath, attrs) in self.attributes{
if CGRectIntersectsRect(rect, attrs.frame) {
attribs.append(attrs)
}
}
var headerAttributes = GridViewRulerAttributes(forSupplementaryViewOfKind: GridRulerView.Kind, withIndexPath: NSIndexPath(forItem: 0, inSection: 0))
headerAttributes.zIndex = 500
headerAttributes.frame = CGRectMake(0, self.collectionView!.contentOffset.y, self.preCalculatedContentSize.width, 80)
attribs.append(headerAttributes)
return attribs
}
When I start the app, everything looks great, exactly how I want it.
BUT as soon as I scroll the collectionView beyond it's bounds (collectionView's contentOffset = (-0.5,-0.5) <- any negative values for example) I get a crash:
*** Assertion failure in -[UICollectionViewData validateLayoutInRect:], /SourceCache/UIKit/UIKit-3318.16.25/UICollectionViewData.m:426
The interesting thing is that if I set the header view attribute's frame's y property to 0 instead of the variable contentOffset.y (which becomes negative), everything works fine.
Anybody any idea why this happens ?
EDIT
Here is a more informative error message:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'layout attributes for supplementary item at index path ( {length = 2, path = 0 - 0}) changed from index path: ( {length = 2, path = 0 - 0}); element kind: (GridRulerViewKind); frame = (0 0; 425.227 24); zIndex = 500; to index path: ( {length = 2, path = 0 - 0}); element kind: (GridRulerViewKind); frame = (0 -5; 425.227 24); zIndex = 500; without invalidating the layout'
Wow, actually disabled "All Exceptions" breakpoints and got a more informative error to work with:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'layout attributes for supplementary item at index path ( {length = 2, path = 0 - 0}) changed from index path: ( {length = 2, path = 0 - 0}); element kind: (GridRulerViewKind); frame = (0 0; 425.227 24); zIndex = 500; to index path: ( {length = 2, path = 0 - 0}); element kind: (GridRulerViewKind); frame = (0 -5; 425.227 24); zIndex = 500; without invalidating the layout'
Now, I still had no idea what to do, or where to
"invalidate the layout"
Then while browsing similar questions, I came across a similar question here on SO where I stumbled upon this simple function:
override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool{
return true
}
And sure enough, that seemed to work! No crash anymore!
EDIT
Actually, this is causing the collection view layout to invalidate on every scroll, so this does not seem to be the solution I am looking for...
Edit #2
After a bit of research, I don't think it is possible to create a supplementary view that changes by itself without invalidating the layout (which kind of seems perfectly logical - how would the layout know to just update the ruler view without explicitly saying so ?). And updating the layout on each scroll is just way too expensive.
So I figured I will just create a separate view which is entirely independent of the collection view and simply listening to the collection view's scroll delegate and adjusting its frame according to the scroll offset. I think this approach is much more efficient in terms of performance and is equally easy to implement.
Solution
Just check representedElementKind
class CustomFlowLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let attributesForElementsInRect = super.layoutAttributesForElements(in: rect)
var newAttributesForElementsInRect = [UICollectionViewLayoutAttributes]()
for attributes in attributesForElementsInRect! {
if !(attributes.representedElementKind == UICollectionElementKindSectionHeader
|| attributes.representedElementKind == UICollectionElementKindSectionFooter) {
// cells will be customise here, but Header and Footer will have layout without changes.
}
newAttributesForElementsInRect.append(attributes)
}
return newAttributesForElementsInRect
}
}
class YourViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let headerNib = UINib.init(nibName: "HeaderCell", bundle: nil)
collectionView.register(headerNib, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "HeaderCell")
let footerNib = UINib.init(nibName: "FooterCell", bundle: nil)
collectionView.register(footerNib, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: "FooterCell")
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionHeader:
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "HeaderCell", for: indexPath) as! HeaderCell
return headerView
case UICollectionElementKindSectionFooter:
let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "FooterCell", for: indexPath) as! FooterCell
return footerView
default:
return UICollectionReusableView()
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 45)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 25)
}
}
Why you are passing GridRulerView.Kind for ReuseIdentifier?
reusableHeaderView = collectionView.dequeueReusableSupplementaryViewOfKind(GridRulerView.Kind, withReuseIdentifier: **GridRulerView.Kind**, forIndexPath: indexPath) as! UICollectionReusableView
It should be as below.
var supplementaryView =
collectionView.dequeueReusableSupplementaryViewOfKind(kind,
withReuseIdentifier:Identifiers.HeaderIdentifier.rawValue,
forIndexPath: indexPath) as UICollectionReusableView

Resources