I've got a UICollectionView with a custom class that is subclassing UICollectionViewCell. I keep getting the following error:
reason: 'could not dequeue a view of kind:
UICollectionElementKindCell with identifier Appointment - must
register a nib or a class for the identifier or connect a prototype
cell in a storyboard'
I have however done the following:
Registered the custom class with the collectionView.
self.collectionView.registerClass(AppointmentCollectionViewCell.self, forCellWithReuseIdentifier:"Appointment");
Here is my dequeue line:
let appointmentCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("Appointment", forIndexPath: indexPath) as! AppointmentCollectionViewCell;
This is what my AppointmentCollectionViewCell looks like:
class AppointmentCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var leftBorderView: UIView!
#IBOutlet weak var appointmentLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
func setAppointment(appointment:Appointment){
self.leftBorderView.backgroundColor = appointment.eventColour;
self.appointmentLabel.textColor = appointment.eventColour;
self.backgroundColor = appointment.eventColour.colorWithAlphaComponent(0.2);
}
}
I have also in the view provided the reuse identifier to be "Appointment".
I've also tried the following based on answers posted here - still not working:
let appointmentNib = UINib(nibName: "AppointmentCollectionViewCell", bundle:NSBundle.mainBundle())
self.collectionView.registerNib(appointmentNib, forCellWithReuseIdentifier: "Appointment")
After googling, most people forget to register the class. In my case I have registered the class but still keep getting the error. Where am I going wrong?
If your cell is associated with a xib file you need to use the registerNib method, not the registerClass method.
func registerNib(_ nib: UINib?, forCellWithReuseIdentifier identifier: String)
Documentation
You also seem to be confusing Collection Reusable View and UICollectionViewCell - which is it? Both have specific registration methods, check the documentation.
First Check:
You have a Xib which have class AppointmentCollectionViewCell
Get Nib from class
For e.g.
UINib *favouritesNib = [UINib nibFromClass:[TNYCellRestaurantAnchorclass]];
Register the Nib to CollectionView
[self.collectionViewName registerNib:nib forCellReuseIdentifier:#"identifier name"];
Related
Table view cell in cellForRowAt alway has all properties set to nil
import UIKit
class TodoTableViewCell: UITableViewCell {
#IBOutlet weak var label: UILabel!
}
class TodosViewController: UITableViewController {
#IBOutlet var TodosTableView: UITableView!
var projects = [Project]()
var todos = [Todo]()
override func viewDidLoad() {
super.viewDidLoad()
TodosTableView.delegate = self
self.tableView.register(TodoTableViewCell.self, forCellReuseIdentifier: "TodoTableViewCell1")
// data init
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "TodoTableViewCell1"
var todo = projects[indexPath.section].todos[indexPath.row]
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? TodoTableViewCell else {
fatalError("The dequeued cell is not an instance of MealTableViewCell.")
}
cell.label?.text = todo.text // cell.label is always nil
return cell
}
}
It seems like identical issue
Custom table view cell: IBOutlet label is nil
What I tried to do:
- restart Xcode
- recreate outlet
- clean project
- recreate view cell from scratch like here https://www.ralfebert.de/ios-examples/uikit/uitableviewcontroller/custom-cells/
Please help, iOS development drives me nuts already.
You don't need to register the class in the tableview if you're using prototype cells in Interface Builder. Try removing the registration function from viewDidLoad. Incidentally you can also set dataSource and delegate in IB - much neater code-wise.
You are using the UITableView instance method:
func register(AnyClass?, forCellReuseIdentifier: String)
This only works if your custom UITableViewCell subclass is not setup using Interface Builder
If you've created your subclass using an xib. You should use:
func register(UINib?, forCellReuseIdentifier: String)
like:
let nib = UINib(nibName: "\(TodoTableViewCell.self)", bundle: nil)
self.tableView.register(nib, forCellReuseIdentifier: "TodoTableViewCell1")
If you're using prototype cells in a storyboard you don't need to register your cells at all.
I think the identifier of the cell should be in the identifier from the attributes inspector column not the Identity inspector
and in module in Identity inspector add your project
Important note: One issue I haven't seen discussed is that if you use prototype cells in the storyboard, then explicitly registering the cell will make your outlets nil! If you explicitly register the cell then you are registering it without the storyboard which has your iboutlets. This will mean you defined your outlets in your cell but they aren't connected. Deleting the explicit registration will solve the issue.
Doesn't work:
tableVIew.register(MenuCell.self, forCellReuseIdentifier: "MenuCell")
Works:
// tableVIew.register(MenuCell.self, forCellReuseIdentifier: "MenuCell")
I'm working with nib files for the first time and trying to add a tableview with a tableview cell. I created a nib file of type UIView controller, then I dragged the tableview onto the view, and in the viewcontroller.swift I added all of the necessary delegate, datasource, cellForRowatIndexPath, numberOfRowsinSection, etc, just like normal. But the app crashes on loading. I have looked at several other questions, notably these:
Custom UITableViewCell from nib in Swift
Can't make UiTableView work
But those solutions did not work for me completely and it still crashes on loading. Another error message I've gotten has been "this class is not key value compliant."
So, what are the exact steps to make a uitableview in a nib file? From what I understand:
File--> New-->File-->Cocoa Touch Class-->Subclass UITableViewController. this sets up the table view. we will call this View1.swift
File-->New-->File-->Cocoa Touch Class-->Subclass UITableViewCell. this sets up the cell in the tableview. we'll call this View1TableCell.swift
in View1.swift, register the nib:
tableView.registerNib(UINib(nibName: "View1", bundle: nil), forCellReuseIdentifier: "View1CellID")
Give the cell a reuse identifier. We will say this is "View1CellID"
in View1.swift, in cellforRowAtIndexPath, dequeue the cell with the correct cell identifier.
So, all these steps should work so that I can add any label or button to my View1TableCell nib, and those changes will be seen on the tableview when I build and run, correct? What am I doing wrong?
The nib you register should be the one containing the cell, not the view controller. From Apple docs:
Parameters
A nib object that specifies the nib file to use to
create the cell. This parameter cannot be nil.
So the view that holds your table is View1, from your explanation.
If you want to implement a custom cell, you need to create a new class, to extend UITableViewCell. That class should also have a nib
So create a new class
class MyCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
setupCell()
}
func setupCell() {
//setup your ui here
}
}
Now in View1.swift, in viewDidLoad, register the nib
func viewDidLoad() {
super.viewDidLoad()
//register the nib of the cell for your cell
tableView.registerNib(UINib(nibName: "MyCell", bundle: nil), forCellReuseIdentifier: "MyCellIdentifier")
}
now use the cell in your tableview
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("MyCellIdentifier") as! MyCell
//set the stuff you need in your cell
return cell
}
I recently tried changing my UITableViewController to a UITableView within a UIView. I changed back to this as I was experiencing an error with my UISearchBar, as when I would tap a key to search my app would crash with the error:
fatal error: unexpectedly found nil while unwrapping an Optional value
on this line:
var cell = tableView.dequeueReusableCellWithIdentifier("rideCell") as! RideCell
When I switched back to the UITableViewController this error went away and everything was fine, however I've just tested it again and it is again giving me that error.
Anyone have any suggestions? It works fine for the normal table view, it's just when I go to do a search that it crashes. The identifier is definitely correct.
Thanks!
EDIT:
Full function:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("rideCell", forIndexPath: indexPath) as! RideCell
var ride: Ride
if tableView == self.searchDisplayController?.searchResultsTableView {
ride = DataManager.sharedInstance.getRideByName(searchResults[indexPath.row].name)!
} else {
ride = DataManager.sharedInstance.rideAtLocation(indexPath.row)!
}
cell.rideNameLabel.text = ride.name
var dateSinceUpdate = NSDate().timeIntervalSinceDate(ride.updated!)
var secondsSinceUpdate = Int(dateSinceUpdate)
var timeSinceUpdate = printSecondsConvert(secondsSinceUpdate)
cell.updatedLabel.text = timeSinceUpdate
if ride.waitTime == "Closed" {
cell.waitTimeLabel.text = ride.waitTime!
cell.timeBackgroundView.backgroundColor = getColorFromNumber(80)
cell.waitTimeLabel.font = UIFont(name: "Avenir", size: 13)
} else {
cell.waitTimeLabel.text = "\(ride.waitTime!)m"
cell.timeBackgroundView.backgroundColor = getColorFromNumber(ride.waitTime!.toInt()!)
cell.waitTimeLabel.font = UIFont(name: "Avenir", size: 17)
}
AsyncImageLoader.sharedLoader().cancelLoadingURL(cell.rideImageView.imageURL)
cell.rideImageView.image = UIImage(named: "Unloaded")
cell.rideImageView.imageURL = NSURL(string: ride.rideImageSmall!)
return cell
}
Discovered an extremely simple solution to the issue. Had to change this:
var cell = tableView.dequeueReusableCellWithIdentifier("rideCell", forIndexPath: indexPath) as! RideCell
to this:
var cell = self.tableView.dequeueReusableCellWithIdentifier("rideCell", forIndexPath: indexPath) as! RideCell
There are a few possibilities that you are seeing a fatal error of nil message in your dialog.
Possibility #1: Make sure you have a subclass of UITableViewCell named RideTableViewCell.swift.
To create a subclass of UITableViewCell simply follow the procedures below.
Right-Click on your Project name and create New File... in
Project Navigator
From iOS->Source create Cocoa Touch Class
In Option Dialog Subclass Field Type UITableViewCell
I believe you have an Custom XIB file already, if not, Check Also create XIB file
Make sure you input your XIB identifier in Attribute Inspector
Register your cell class in viewDidLoad() function like so:
let nibCell = UINib(nibName: "RideTableViewCell", bundle: nil)
self.tableView.registerNib(nibPosts, forCellReuseIdentifier: "RideCell")
Register your custom cell in cellForRowAtIndexPath like so:
let cell: RideTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("RideCell", forIndexPath: indexPath) as! RideTableViewCell
Possibility #2: Maybe when you create your custom XIB you didn't tell it which class it belongs to. To set the class of XIB, follow the procedures below.
Click on your .xib file in Project Navigator
Go to identity inspector of your cell and make sure RideTableViewCell is in there.
Please comment if you have any question. Cheers!
Please check did you have given proper class name (RideCell), filled proper module(Your target) and finally the identifier in the storyboard. If this is ok please share SS of your storyboard tableView cell.
and
Hope it helps
If you are not using UITableViewController, then check the following extension are added or not.
class XYZViewController: UIViewController, UITableViewDataSource, UITableViewDelegate,UISearchBarDelegate, UISearchDisplayDelegate, UISearchResultsUpdating
{
or Check this Tutorial. It might help you to solve this error.
Please check that your delegates have been properly set in viewDidLoad and that you are inheriting delegate methods of UITableView and search functions like so:
class YourClass: UIViewController, UITableViewDelegate, UITableViewDataSource {
func viewDidLoad() {
tableView.delegate = self
tableView.dataSource = self
}
}
and do the same for the search bar delegates and data sources. More on that here.
It is showing nil because there is no UItableViewCell which is of type RideCell. You have to create a new RideCell.swift which will be a subclass of UITableViewCell and then associate that with the cell of your tableView and then proceed .
Make sure you fill the correct parameters in the code below.
private let cellReuseIdentifier = "MyCell"
tableView.registerNib(UINib(nibName: "MyCell", bundle: nil), forCellReuseIdentifier: cellReuseIdentifier)
I've linked output from the IB to the code, as shown below.
class DiaryTableViewCell: UITableViewCell {
#IBOutlet weak var TitleLabel: UILabel!
#IBOutlet weak var SubTitleLabel: UILabel!
#IBOutlet weak var leftImageView: UIImageView!
#IBOutlet weak var rightImageView: UIImageView!
}
Here, I'm registering the class:
override func viewDidLoad() {
self.title = "My Diary"
cellNib = UINib(nibName: "TableViewCells", bundle: nil)
tableView.registerClass(DiaryTableViewCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)
}
But I keep getting the following runtime error:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '...setValue:forUndefinedKey:]: this class is not key value
coding-compliant for the key SubTitleLabel.'
From within the following code:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) as DiaryTableViewCell?
if (cell == nil) {
tableView.registerClass(DiaryTableViewCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)
cell = cellNib?.instantiateWithOwner(self, options: nil)[0] as? DiaryTableViewCell
cell?.selectionStyle = .None
}
if (cell != nil) {
println("\(x++)) Inside cell")
cell!.TitleLabel.text = "Hello"
cell!.SubTitleLabel.text = "World"
}
return cell!
}
Specifically, it's happening here:
cell = cellNib?.instantiateWithOwner(self, options: nil)[0] as? DiaryTableViewCell
Question: How am I violating the key value coding-compliant for a UILabel?
This hasn't happened before... UILabel is KVO compliant.
I linked to the WRONG Source!
Here's the result:
You should not be calling instantiateWithOwner yourself inside tableView:cellForRowAtIndexPath.
Register the nib in viewDidLoad and then dequeueReusableCellWithIdentifier will do all the work for you.
The reason for your particular error is that you are calling instantiateWithOwner passing self as the owner and so the nib is trying to wire the outlets up to your UITableViewDataSource implementation class rather than a DiaryTableViewCell.
Show the references of your ViewController rigth-clicking in it on the Document Outline. Probably you will see a warning in one of the references. Delete it and link it again if still need it.
sometimes its like when you create button in your xib, you create one button and copy paste other buttons from one buttons, in that case this error occurs, and yes removed connections from xib could also be an reason.
I have created a TableViewCell same like your & have the same problem. I have research solving the problem but nothing. Then I delete Label in TableViewCell and recreate again, connect it to TableViewCell through File Owner,v..v And the result is right. No error. You should recreate them again.
In My Project I created Cell in UICollectionViewCell
Its got Error Terminating app due to uncaught exception
The code as follow.
GalleryCell.swift
class GalleryCell: UICollectionViewCell
{
#IBOutlet var titleLabel : UILabel
init(coder aDecoder: NSCoder!)
{
super.init(coder: aDecoder)
}
}
and I used this cell in My ViewController:
The code as follow :
NextViewController.swift
import UIKit
class NextViewController: UIViewController
{
#IBOutlet var collectionView : UICollectionView
var ListArray=NSMutableArray()
override func viewDidLoad()
{
super.viewDidLoad()
for i in 0..70
{
ListArray .addObject("C: \(i)")
}
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section:Int)->Int
{
return ListArray.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath:NSIndexPath)->UICollectionViewCell
{
var cell = collectionView.dequeueReusableCellWithReuseIdentifier("CELL", forIndexPath: indexPath) as GalleryCell
cell.titleLabel.text="\(ListArray.objectAtIndex(indexPath.item))"
return cell
}
func collectionView(collectionView : UICollectionView,layout collectionViewLayout:UICollectionViewLayout,sizeForItemAtIndexPath indexPath:NSIndexPath) -> CGSize
{
return CGSizeMake(66, 58)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
My issue is I am getting following 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'*** First throw call stack:**
I added the following two lines in NextViewController.swift under viewDidLoad():
var nibName = UINib(nibName: "GalleryCell", bundle:nil)
collectionView.registerNib(nibName, forCellWithReuseIdentifier: "CELL")
The problem was that I was not registering the nib. Now that I'm doing that, it's working fine.
the same for header/footer in swift:
// register header accessory view:
self.collectionView.registerClass(UICollectionReusableView.self,
forSupplementaryViewOfKind: UICollectionElementKindSectionHeader,
withReuseIdentifier: headerReuseIdentifier);
You need to register a cell class.
In your viewDidLoad write.
collectionView.registerClass(NSClassFromString("GalleryCell"),forCellWithReuseIdentifier:"CELL");
Prior to calling the
dequeueReusableCellWithReuseIdentifier:forIndexPath: method of the
collection view, you must use this method or the
registerNib:forCellWithReuseIdentifier: method to tell the collection
view how to create a new cell of the given type. If a cell of the
specified type is not currently in a reuse queue, the collection view
uses the provided information to create a new cell object
automatically.
If you previously registered a class or nib file with the same reuse
identifier, the class you specify in the cellClass parameter replaces
the old entry. You may specify nil for cellClass if you want to
unregister the class from the specified reuse identifier.
Reference registerClass:forCellWithReuseIdentifier:
I wanted to add another answer that helped me, in case it becomes useful to someone else.
It seems that everyone else has solved this problem through the use of registerNib:forCellWithReuseIdentifier: or registerClass:forCellWithReuseIdentifier:. For me, there was a different resolution: in my storyboard, I selected the header and looked over in the Identity Inspector in the top section where it has fields for my Custom Class. Specifically, the Module field was blank. I needed to pull down the arrow next to that field and select the right target.
Once I did this & saved the storyboard, the above crash no longer happened and I could see my custom header.