This is driving me insane. I've put together dozens of collections views in the past, but this one is refusing to work.
I have a xib for my collection view cell, and I gave it an identifier, "My Cell". In my controller, I do the following:
override func awakeFromNib() {
super.awakeFromNib()
myCollectionView.delegate = self
myCollectionView.dataSource = self
// Register the collection view cell
myCollectionView.register(UINib(nibName: "MyCell", bundle: nil), forCellWithReuseIdentifier: "MyCell")
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath as IndexPath) as? MyCell else {
fatalError("The dequeued cell is not an instance of MyCell.")
}
return cell
}
Yet no matter what I do, Xcode is crashing and giving me this error:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'could not dequeue a view of kind: UICollectionElementKindCell with identifier MyCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
I've tried cleaning the build folder, restarting Xcode, even restarting my Mac, and nothing works.
What am I doing wrong??
Check if you are providing the same exact identifier. Copy/Paste to make sure they are the same.
I think you have to check two things
use this myCollectionView.dequeueReusableCell
`
override func awakeFromNib() {
super.awakeFromNib()
myCollectionView.delegate = self
myCollectionView.dataSource = self
// Register the collection view cell
myCollectionView.register(UINib(nibName: "MyCell", bundle: nil), forCellWithReuseIdentifier: "MyCell")
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = myCollectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath as IndexPath) as? MyCell else {
fatalError("The dequeued cell is not an instance of MyCell.")
}
return cell
}`
Open Xib file and check whether reusable identifier is set or not
Hope this will solve your issue , if not let me know
I want to do something similar to this where A, B and C are all different UICollectionViewController. My current approach is manually duplicating the cell in storyboard to all different UICollectionViews but have they all have same custom subclass. However, it's not DRY for UI development and I have to manually change replicate the changes in each UICollectionViewCell copy.
I know XIBs can be used to achieve this, but I'm stuck at how to link it with all UICollectionViewController through storyboard or minimal Swift code.
#Anushik use below steps to create custom cell using xib and reuse
1.Create UICollectionViewCell subclass along with xib
2.Add reuse identifier to the cell
3.Register the nib using register(nib:forCellWithReuseIdentifier) method in viewDidLoad method in UIViewController class
let nib = UINib(nibName: "CustomCollectionViewCell", bundle: nil)
collectionView.register(nib, forCellWithReuseIdentifier: "CustomCell")
4.Use the custom cell in cellForItemAt method of UICollectionViewDatasource
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCollectionViewCell
let item = items[indexPath.row]
cell.configureCell(item: item)
return cell
}
I'm working with an UICollectionView. As dequeueReusableCell(withReuseIdentifier:for:) expects You must register a class or nib file using the register(_:forCellWithReuseIdentifier:) method before calling this method, I added a line in my viewDidLoad func as
self.collectionView!.register(PhotoCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
Now when I'm using the cell for dequeuing and configuring, I'm getting error and app crashes.
fatal error: unexpectedly found nil while unwrapping an Optional value
This is my DataSource method:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier,
for: indexPath) as! PhotoCollectionViewCell
let aPhoto = photoForIndexPath(indexPath: indexPath)
cell.backgroundColor = UIColor.white
cell.imageView.image = aPhoto.thumbnail //this is the line causing error
return cell
}
And this is my PhotoCollectionViewCell class
class PhotoCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var imageView: UIImageView! //I double checked this IBOutlet whether it connects with Storyboard or not
}
Original question
Now comes the interesting part.
I'm using a prototype cell in the UICollectionView and I set a reusable identifier from attributes inspector. Also I changed the custom class from identity inspector to my PhotoCollectionViewCell.
I searched for the same issue and found out that when using prototype cell, deleting
self.collectionView!.register(PhotoCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
from code will work. I gave it a try and it works.
But I'm curious to know the reason behind this issue. I couldn't reproduce the same issue with UITableView but with UICollectionView.
Not a possible duplicate:
This UICollectionView's cell registerClass in Swift is about how to register class in UICollectionView. But my question doesn't expect how to register. My question is about an issue that isn't true with UITableView class but with UICollectionView only. I'm expecting the actual difference between this conflicting issue.
There are 3 ways to register a cell (either for UITableView or UICollectionView).
You can register a class. That means the cell has no nib or storyboard. No UI will be loaded and no outlets connected, only the class initializer is called automatically.
You can register a UINib (that is, a xib file). In that case the cell UI is loaded from the xib and outlets are connected.
You can create a prototype cell in the storyboard. In that case the cell is registered automatically for that specific UITableViewController or UICollectionViewController. The cell is not accessible in any other controller.
The options cannot be combined. If you have a cell prototype in the storyboard, you don't have to register again and if you do, you will break the storyboard connection.
You can assign Nib to Collection view cell with an identifier as follows :
self.collectionView.register(UINib(nibName: "nibName", bundle: nil), forCellWithReuseIdentifier: "cell")
Hope it helps.
I have never used UICollectionViewControllers, and I thought that they were somewhat similar to UITableViewControllers, but to my surprise, I cannot add UI elements to my custom UICollectionViewCells in the same way as I do with custom UITableViewCells.
In fact, I can add labels, buttons, etc. in the Interface Builder, but when I run the application, the cells appear empty.
I have registered the cell class during the viewDidLoad method by calling (void)registerClass:(Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier, and I've checked that I am returning a valid instance of UICollectionViewCellin the (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath method.
What am I doing wrong?
My full explanation is here.
Create a custom class for the UICollectionViewCell:
import UIKit
class MyCollectionViewCell: UICollectionViewCell {
// have outlets for any views in your storyboard cell
#IBOutlet weak var myLabel: UILabel!
}
In the storyboard make the cell use this class
And set the Identifier for the cell
Don't use the registerClass...forCellWithReuseIdentifier in viewDidLoad. But you will refer to it in collectionView...cellForItemAtIndexPath:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! MyCollectionViewCell
// Use the outlet in our custom class to get a reference to the UILabel in the cell
cell.myLabel.text = self.items[indexPath.item]
cell.backgroundColor = UIColor.yellowColor()
return cell
}
Hook up the outlets from the Views in your storyboard cell to the MyCollectionViewCell class.
#Suragch is spot on. I had this problem too: my UICollectionViewCell prototype's contents did not show in the cell when it got drawn.
The critical line is: "Don't use the registerClass...forCellWithReuseIdentifier in viewDidLoad". Really, don't. Not just "there is no need to", but "if you do register, it will stop your cell prototype from loading properly".
This only applies to Storyboard-based code, not .xib-based.
if you want to use registerClass...forCellWithReuseIdentifier, then you should do it this way:
let nib = UINib(nibName: "TrackCollectionViewCell", bundle: nil)
collectionView.register(nib, forCellWithReuseIdentifier: "trackCellIdentifier")
Taking first plunge with collection views and am running into this error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'could not dequeue a view of kind: UICollectionElementKindCell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
The code is very simple, as shown below. I can't for the life of me figure out what it is that I'm missing.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
The collection view controller was created using a nib and the delegates & datasources are both set to file's owner.
View Controller's header file is also really basic.
#interface NewMobialViewController_3 : UICollectionViewController <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
#end
From the UICollectionView documentation for the dequeue method:
Important: You must register a class or nib file using the registerClass:forCellWithReuseIdentifier: or registerNib:forCellWithReuseIdentifier: method before calling this method.
You need to use same identifier between the dequeueReusableCellWithReuseIdentifier's argument and the UICollectionViewCell's property.
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CollectionViewCell" forIndexPath:indexPath];
Complementing what #jrtuton written... What you need is:
1) Register your nib file to "connect" it with your identifier:
//MyCollectionView.m
- (void) awakeFromNib{
[self registerNib:[UINib nibWithNibName:#"NibFileName" bundle:nil] forCellWithReuseIdentifier: #"MyCellIdentifier"];
}
2) Use your identifier to load your custom cell from a nib:
//MyCollectionView.m
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MyCustomCollectionViewCell* cell = [cv dequeueReusableCellWithReuseIdentifier:#"MyCellIdentifier" forIndexPath:indexPath];
}
3) Use always static NSString* to avoid the same identifiers again in your app.
Swift 5
1) Make sure you have a correct deque for HEADER, you might be using the regular for normal cells.
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath)
return header
}
2) doubleCheck the registration (ViewDidLoad)
collectionView.register(HeaderCell.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: headerId)
i had everything 100% done correctly.
but for some reason i got the same error for an hour, then what i did is:
go to storyboard
select the prototype cell (in my case)
clear the class name from identity inspector, then rewrite it
rewrite the identifier name in the attributes inspector
simply, redid this step even tho i made it correct before, its like xcode misses something at a specific nanosecond!
Swift4.0
Whenever your UITableViewCell is xib at that time you must have to register with UITableView.
override func viewDidLoad(){
super.viewDidLoad()
self.yourtableview.register(UINib(nibName: "yourCellXIBname", bundle: Bundle.main), forCellReuseIdentifier: "YourCellReUseIdentifier")
}
Please be sure to check the ViewController Custom Class correct if the project is having multiple ViewControllers. And then make sure whatever the "collectionView.dequeueReusableCell(withReuseIdentifier: "ABC", for: indexPath) as?" matches with the identifier used in Collection Reusable View inside the Collection View.
If you are using storyboard instead of xib, here are few steps.
Making sure you fill the right identifier of your cell.
In the ColletionViewDelegate.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourCellName", for: indexPath)as! YourCellName
return cell
}
That's it. You also don't want to add registerClass:forCellWithReuseIdentifier: which will cause element nil error.
You need to give correct reuseble identifier in storyboard, which you have give in the code while registering the collectionViewCell.
Here is the code.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ClctnVC", for: indexPath)as! ClctnVC
return cell
}
What fixed this for me was (roughly) same as Omar's answer, except I ended up creating a new UICollectionViewCell custom class and giving the Cell Reuse Indentifier a new / different name than the one that I had used elsewhere in the application. It worked immediately after that.
Just in case, if you are working with storyboard set collectionView identifier in the right place in the Attributes Inspector -> Identifier field. Not under the class name in "Restoration ID".
If you are using collection view in tableView cell, add delegates to tableView cell not in the tableViewController.
I had the same problem.
When I created a CollectionViewController, the default reuseIdentifier was Cell with capital C, but I made a mistake and made my cell identifier in Storyboard to be cell
They must be the same.
If you ever try solution in answer another in issue not work but in code is correct syntax ,correct outlet UI.
You should check in you tableview or collectionview then check you maybe forget set delegate "tableview.delegate = self or collectionview.delegate = self"
collectionview.delegate = self
collectionview.dataSource = self
In my case is only you design collection overlap collection in your cell.
thank you.
I know this is an old one, but I've experienced the same problem and wanted to share what fixed it for me.
In my case, I've declared a global identifier
let identifier = "CollectionViewCell"
and had to use self right before using it:
collectionView.dequeueReusableCellWithReuseIdentifier(self.identifier, forIndexPath: indexPath) as! CollectionViewCell
Hope this helps someone :)
If you create it by code, you must create a custom UICollectionViewCell, Then, init a UICollectionView ,and use loadView to set the view is the UICollectionView that you create. If you create in viewDidload() , it does not work. In addition, you can also drag a UICollectionViewController, it saves a lot of time.