UICollectionView.dequeueReusableCell crashes - ios

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?

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.

Could not cast value of type 'UITableViewCell' (0x1096e3580) to 'SwipeCellKit.SwipeTableViewCell' (0x106d231d0)?

I have a TableVC which has categories when you tap on one it takes you to the items within it. But when I do this I get the following grouping of multiple errors when the app crashes:
1.
error initializing newrealm, Error Domain=io.realm Code=1 "Provided
schema version 0 is less than last set version 1."
UserInfo={NSLocalizedDescription=Provided schema version 0 is less
than last set version 1., Error Code=1}
2.
2018-08-01 12:56:06.152225-0400 Todoey[35380:4690261] Unknown class
SwipeTableViewCell in Interface Builder file.
3.
Could not cast value of type 'UITableViewCell' (0x1096e3580) to
'SwipeCellKit.SwipeTableViewCell' (0x106d231d0).
4.
2018-08-01 12:56:06.153831-0400 Todoey[35380:4690261] Could not cast
value of type 'UITableViewCell' (0x1096e3580) to
'SwipeCellKit.SwipeTableViewCell' (0x106d231d0).
I have followed the steps laid out in many previous questions but no luck
This is where I get a -Thread 1: signal SIGABRT-
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! SwipeTableViewCell
cell.delegate = self
return cell
}
Help please
all you have to do, select your tableViewCell -> go to identity Inspector -> select the custom class as SwipeTableViewCell and module as SwipeCellKit. then run...
I think you are overriding the registration of cell to your table view, with the method:
#available(iOS 6.0, *)
open func register(_ cellClass: AnyClass?, forCellReuseIdentifier identifier: String)
and somewhere in viewDidLoad, or viewDidAppear, or viewWillAppear you registered to tableView a simple UITableCell.self instead a custom cell, as bellow :
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
In case you create the SwipeTableViewCell programatically use this method in viewDidLoad as bellow:
self.tableView.register(SwipeTableViewCell.self, forCellReuseIdentifier: "Cell")
In case your SwipeTableViewCell is created in storyboards, I don't recommend to use this method, because you override the constructor, and your objects inside the SwipeTableViewCell need to be initialized programatically. Just remove the registration line, because in the storyboard you have registered the custom cell. Take care to have set identifier for cell.
Although it is not in the question, I encountered the same problem on the same tutorial, so same app. This might help some future passersby.
It should work with:
let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryCell", for: indexPath) as! SwipeTableViewCell
It WILL NOT work with:
let cell = UITableViewCell(style: .default, reuseIdentifier: "CategoryCell") as! SwipeTableViewCell

TableView CellReuse

I have problems with my custom cell file in tableview. I managed to get it done using the out comment line shown below, but the performance was really bad when it had 10+ cells.
UsingdequeueReusableCell leads to this error:
'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier DiveNewsShort - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
which is strange, because I do register the nib in viewDidLoad(). I hope you can help me, I am getting frustrated by this.
class ProfilTableView: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UINib(nibName: "DiveNewsShort", bundle: nil), forCellReuseIdentifier: "DiveNewsShort")
tableView.register(DiveNewsShort.self, forCellReuseIdentifier: "DiveNewsShort")
}
public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// let cell = Bundle.main.loadNibNamed("DiveNewsShort", owner: self, options: nil)?.first as! DiveNewsShort
// This one works as expected
let cell = tableView.dequeueReusableCell(withIdentifier: "DiveNewsShort", for: indexPath) as! DiveNewsShort
// This one does not
return cell }
Update:
I managed to get rid of the error by adding the register function in the cellForRowAt function, but I don't think that this is a efficient way actually. It should work within the vieDidLoad shouldn't it?
public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
tableView.register(UINib(nibName: "DiveNewsShort", bundle: nil), forCellReuseIdentifier: "DiveNewsShort")
let cell = tableView.dequeueReusableCell(withIdentifier: "DiveNewsShort", for: indexPath) as! DiveNewsShort
return cell }
You don't need this line:
tableView.register(DiveNewsShort.self, forCellReuseIdentifier: "DiveNewsShort")
You already have registered the nib file one line before.
There are three ways to register cells for reuse/dequeuing:
You are programmatically creating the cells, in which case you register the class in viewDidLoad.
You are using a NIB, in which case you register the NIB in viewDidLoad.
You are using storyboard cell prototypes, in which case you don't have to register anything. The storyboard does all of this for you.
Since you are using NIBs, you should remove the registering of the class and only register the NIB. And you should do this in viewDidLoad. This process is outlined in https://stackoverflow.com/a/28490468/1271826 as well as in Reinier's answer.
Looking at your MCVE, your problem was a result of a more fundamental mistake, where you had a UIViewController trying to use another view controller, which was a UITableViewController, to manage the table. But UITableViewController has its own UITableView and won't use the one that you have an #IBOutlet for, so you were registering the NIB for a table view you weren't seeing. There were a ton of other issues here (e.g. if you really want a view controller within a view controller, you have to do view controller containment calls, etc.), but the simplest solution was to excise this separate UITableViewController from the project and when this was fixed, it works precisely as we described. See https://github.com/robertmryan/Divers for a working version of your MCVE.
You also didn't hook up the outlets for the other two controls in your cell (the switch and slider). Thus, if you changed either of those two controls and then scrolled, the cells are reused and you see the changed UIKit control that was done for some other cell, but was subsequently reused. To fix that, your custom UITableViewCell subclass should have outlets for all controls, and cellForRowAt must set values for all of these outlets. You also need some mechanism for the cell to inform the view controller when the switch and slider have changed and update the model accordingly, so when cellForRowAt was later called for that row, it would know the state of that CellData to set the control appropriately. A common solution for this is to use the protocol-delegate pattern. See the above GitHub repo, which illustrates this pattern, too.
I have build this protocol for help me in this process
protocol CBNibInstanceableCellProtocol {
static func getCellXib() -> UINib?
static func getReuseIdentifier() ->String
}
and in your class you have to implement those methods like here
//example implementation
extension CBUsersAttendanceEmptyCell : CBNibInstanceableCellProtocol
{
static func getCellXib() -> UINib?
{
if Bundle.main.path(forResource: "CBUsersAttendanceEmptyCell", ofType: "nib") != nil
{
return UINib(nibName: "CBUsersAttendanceEmptyCell", bundle: nil)
}
return nil
}
static func getReuseIdentifier() ->String
{
return "CBUsersAttendanceEmptyCell"
}
}
then in your viewDidLoad you must do something like this
//example code
self.collectionView.register(CBUsersAttendanceAvatarCell.getCellXib(), forCellWithReuseIdentifier: CBUsersAttendanceAvatarCell.getReuseIdentifier())
self.collectionView.register(CBUsersAttendanceCountCell.getCellXib(), forCellWithReuseIdentifier: CBUsersAttendanceCountCell.getReuseIdentifier())
self.collectionView.register(CBUsersAttendanceEmptyCell.getCellXib(), forCellWithReuseIdentifier: CBUsersAttendanceEmptyCell.getReuseIdentifier())
in your cellForRow
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CBUsersAttendanceCountCell.getReuseIdentifier(), for: indexPath) as? CBUsersAttendanceCountCell
{
return cell
}
You must have defined the class for you view in your xib, this is very important check this pictures
Hope this helps

unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard

My UITableViewController is causing a crash with the following error message:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
I understand that I need to register a nib or a class but I don't understand 'where or how?'.
import UIKit
class NotesListViewController: UITableViewController {
#IBOutlet weak var menuButton: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "preferredContentSizeChanged:",
name: UIContentSizeCategoryDidChangeNotification,
object: nil)
// Side Menu
if self.revealViewController() != nil {
menuButton.target = self.revealViewController()
menuButton.action = "revealToggle:"
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
// whenever this view controller appears, reload the table. This allows it to reflect any changes
// made whilst editing notes
tableView.reloadData()
}
func preferredContentSizeChanged(notification: NSNotification) {
tableView.reloadData()
}
// #pragma mark - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return notes.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let note = notes[indexPath.row]
let font = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)
let textColor = UIColor(red: 0.175, green: 0.458, blue: 0.831, alpha: 1)
let attributes = [
NSForegroundColorAttributeName : textColor,
NSFontAttributeName : font,
NSTextEffectAttributeName : NSTextEffectLetterpressStyle
]
let attributedString = NSAttributedString(string: note.title, attributes: attributes)
cell.textLabel?.font = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)
cell.textLabel?.attributedText = attributedString
return cell
}
let label: UILabel = {
let temporaryLabel = UILabel(frame: CGRect(x: 0, y: 0, width: Int.max, height: Int.max))
temporaryLabel.text = "test"
return temporaryLabel
}()
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
label.font = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)
label.sizeToFit()
return label.frame.height * 1.7
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
notes.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
}
// #pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if let editorVC = segue.destinationViewController as? NoteEditorViewController {
if "CellSelected" == segue.identifier {
if let path = tableView.indexPathForSelectedRow() {
editorVC.note = notes[path.row]
}
} else if "AddNewNote" == segue.identifier {
let note = Note(text: " ")
editorVC.note = note
notes.append(note)
}
}
}
}
You can register a class for your UITableViewCell like this:
With Swift 3+:
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
With Swift 2.2:
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
Make sure same identifier "cell" is also copied at your storyboard's UITableViewCell.
"self" is for getting the class use the class name followed by .self.
Have you set the Table Cell identifier to "Cell" in your storyboard?
Or have you set the class for the UITableViewController to your class in that scene?
This worked for me, May help you too :
Swift 4+ :
self.tableView.register(UITableViewCell.self, forCellWithReuseIdentifier: "cell")
Swift 3 :
self.tableView.register(UITableViewCell.classForKeyedArchiver(), forCellReuseIdentifier: "Cell")
Swift 2.2 :
self.tableView.registerClass(UITableViewCell.classForKeyedArchiver(), forCellReuseIdentifier: "Cell")
We have to Set Identifier property to Table View Cell as per below image,
I had this issue today which was solved by selecting Product -> Clean. I was so confused since my code was proper. The problem started from using command-Z too many times :)
y my case i solved this by named it in the "Identifier" property of Table View Cell:
Don't forgot: to declare in your Class: UITableViewDataSource
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell
Just drag a cell (as you did for TableViewController) and add in to it just by releasing the cell on TableViewController. Click on the cell and.Go to its attributes inspector and set its identifier as "Cell".Hope it works.
Don't forget you want Identifier on the Attributes Inspector.
(NOT the "Restoration ID" on the "Identity Inspector" !)
Match the identifier name at both places
This error occurs when the identifier name of the Tablecell is different in the Swift file and in the Storyboard.
For example, the identifier is placecellIdentifier in my case.
1) The Swift File
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "placecellIdentifier", for: indexPath)
// Your code
return cell
}
2) The Storyboard
One more reason for this issue to happen is an earlier problem. When showing a new ViewController, instantiating the target ViewController directly will of course not load the prototype cells from the StoryBoard. The correct solution should always be to instantiate the view controller through the story board like this:
storyboard?.instantiateViewController(withIdentifier: "some_identifier")
In Swift 3.0, register a class for your UITableViewCell like this :
tableView.register(UINib(nibName: "YourCellXibName", bundle: nil), forCellReuseIdentifier: "Cell")
I had the same problem. This issue worked for me. In storyboard select your table view and change it from static cells into dynamic cells.
My problem was I was registering table view cell inside dispatch queue asynchronously. If you have registered table view source and delegate reference in storyboard then dispatch queue would delay the registration of cell as name suggests it will happen asynchronously and your table view is looking for the cells.
DispatchQueue.main.async {
self.tableView.register(CampaignTableViewCell.self, forCellReuseIdentifier: CampaignTableViewCell.identifier())
self.tableView.reloadData()
}
Either you shouldn't use dispatch queue for registration OR do this:
DispatchQueue.main.async {
self.tableView.dataSource = self
self.tableView.delegate = self
self.tableView.register(CampaignTableViewCell.self, forCellReuseIdentifier: CampaignTableViewCell.identifier())
self.tableView.reloadData()
}
There is two way you can define cell. If your table cell is inside on your ViewControllern then get the cell this way:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
// write your code here
return cell
}
But if you define cell outside of your ViewController then call the sell this way:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = Bundle.main.loadNibNamed("TableViewCell", owner: self, options: nil)?.first as! TableViewCell
// write your code here
return cell
}
And as everyone said don't forget to set your cell identifier:
Stupid mistake:
make sure you add register(TableViewCell.self, forCellReuseIdentifier: "Cell") instead of register(TableViewCell.self, forHeaderFooterViewReuseIdentifier: "Cell")
If you defined your cell through the Interface Builder, by placing a cell inside your UICollectionView, or UITableView :
Make sure you binded the cell with an actual class you created, and very important, that you checked "Inherit module from target"
It used to work on swift 3 and swift 4 but now its not working.
like
self.tableView.register(MyTestTableViewCell.self, forCellReuseIdentifier: "cell")
So I have tried the most of the solutions mentioned above in swift 5 but did not get any luck.
Finally I tried this solution and it worked for me.
override func viewDidLoad()
{
tableView.register(UINib.init(nibName: "MyTestTableViewCell", bundle: nil), forCellReuseIdentifier: "myTestTableViewCell")
}
I just met the same issue and see this post. For me it's because I forgot the set the identifier of cell, also as mentioned in other answers. What I want to say is that if you are using the storyboard to load custom cell we don't need to register the table view cell in code, which can cause other problems.
See this post for detail:
Custom table view cell: IBOutlet label is nil
Swift 5
you need to use UINib method to register cell in viewDidLoad
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.
//register table view cell
tableView.register(UINib.init(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "CustomTableViewCell")
}
I had the same issue where I registered my custom UITableViewCell classes within the viewDidLoad() which threw this error. To fix it what I did was registered the cells within the didSet property observer, as shown below
#IBOutlet tableview : UITableView! {
didSet {
tableview.register(CustomCell.self, forCellReuseIdentifier: "Cell")
}
}
Just for those new to iOS buddies (like me) who decided to have multiple cells and in a different xib file, the solution is not to have identifier but to do this:
let cell = Bundle.main.loadNibNamed("newsDetails", owner: self, options: nil)?.first as! newsDetailsTableViewCell
here newsDetails is xib file name.
I ran into this message when UITableView in the IB was moved into another subview with Cmd-C - Cmd-V.
All identifiers, delegate methods, links in the IB etc. stay intact, but exception is raised at the runtime.
The only solution is to clear all inks, related to tableview in the IB (outlet, datasource, delegate) and make them again.
If anyone is doing Unit Testing on a tableView and you're wondering why this error is appearing, just make sure that if you're using a text fixture, you must declare the system under test (SUT) in the setUp function correctly otherwise this error will keep coming up. It is also crucial you call loadViewIfNeeded() so the outlets between your code and storyboard are connected.
override func setUp() {
super.setUp()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
sutSearch = storyboard.instantiateViewController(identifier:String(describing: SearchTableViewController.self))
sutSearch.loadViewIfNeeded() // To make sure your outlets are connected.
}
In the “Subclass of” field, select UITableViewController.
The class title changes to xxxxTableViewController. Leave that as is.
Make sure the “Also create XIB file” option is selected.
Make sure you have the identifier in the attributes filled out with your cell identifier
I was also struggling with the same problem. I had actually deleted the class and rebuilt it. Someone, the storyboard had dropped the link between prototype cell and the identifier.
I deleted the identifier name and re-typed the identifier name again.
It worked.
If the classic solutions (register identifier for class in code or IB) do not work: try to relaunch Xcode, turns out my storyboard stopped saving edits I was made, including setting the reuse identifier.
My dynamic tableview was working properly, with cell identifier set on the Storyboard and in dequeueReusableCell(withIdentifier:.
I then switched the UITableView content from Dynamic Prototypes to Static Cells.
Running the app immediately caused the error, although the cell's identifier was still set to the same value on the Storyboard.
For a static table view, you must register the cell identifier outside the Storyboard:
tableView.register(EntryNutritionCell.self, forCellReuseIdentifier: "Cell")
or, comment out or remove cellForRowAtIndexPath: entirely. This function isn't really used by the Static table view, but is still called(?) and causes the crash:
// override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
// return cell
// }
'Table View Cell' identifier must match the class identifier.
ex: if your 'Table View Cell' identifier is named "myCellId", then your code should be:
let myCell = tableView.dequeueReusableCell(withIdentifier: "myCellId", for: indexPath).
Also, after hours of troubleshooting i realized that having a GestureRecognizer class in my didLoad() was not allowing me to click table cells. so removing all 'hide keyboard' functionality from didLoad() and other extra code solved it for me.
I was struggling with the same problem. i have already check my reusableCell Identifier it was same as in my code. I deleted line of my code
"let Cell = tableView.dequeueReusableCell(withIdentifier: "CELL", for: indexPath)"
clean build
and write it again!
It worked.

Simple UITableView in Swift - unexpectedly found nil

Pretty simple code:
func numberOfSectionsInTableView(tableView: UITableView?) -> Int {
return 1
}
func tableView(tableView:UITableView!, numberOfRowsInSection section:Int) -> Int {
return 5
}
func tableView(tableView:UITableView!, cellForRowAtIndexPath indexPath:NSIndexPath!) -> UITableViewCell! {
let cell: BookTableViewCell = BookTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "BookCell")
println("ip: \(indexPath.row)")
cell.bookLabel.text = "test"
return cell
}
On the cell.bookLabel.text line I get this:
fatal error: unexpectedly found nil while unwrapping an Optional value
The BookTableViewCell is defined like this:
class BookTableViewCell: UITableViewCell {
#IBOutlet var bookLabel: UILabel
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
}
}
And bookLabel is correctly hooked up in a Prototype cell in the Storyboard. Why am I getting this error?
If you're using storyboard, make sure you don't have this line at the start of your file:
self.tableView.registerClass(CustomTableViewCell.self, forCellReuseIdentifier: "customCell")
It will overwrite the storyboard and as a result, the outlet links in the storyboard are ignored.
I was getting this error because I didn't have the identifier written in the Storyboard of the Custom Cell.
Also make sure it matches you code in:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("CustomTableCell") as CustomTableCell
...
}
Possibly that your view in Main.Storyboard lost its IBOutlet reference in ViewController file, just link it again.
When you create a view in code, its IBOutlet properties don't get hooked up properly. You want the version that you get back from dequeueReusableCellWithIdentifier:
let cell = tableView.dequeueReusableCellWithIdentifier("BookCell") as BookTableViewCell
Do not forget to register nib (tested with Swift3), e. g. inside override func viewDidLoad():
self.tableView.register(UINib(nibName: "BookTableViewCell", bundle: nil), forCellReuseIdentifier: "BookCell")
The reason why this question gets asked a lot is because it depends on how you setup your tableview and custom CellClass. Do you create your tableview in storyboard or programmatically? Do you create custom .xib Cells and custom Cell classes?
If you created your tableview programmatically and created custom .xib and Cell class here is the answer for Swift 4:
in viewDidLoad:
customTable.register(UINib(nibName: "NibName", bundle: nil), forCellReuseIdentifier: "NibNameIdentifier")
in cellforRowat:
let cell = tableView.dequeueReusableCell(withIdentifier: "NibName") as! ClassName
Note: In your cell .xib file make sure you set your identifier in the Attributes inspector ("NibNameIdentifier").
You need to check two things
1. Register cell with nib name in viewDidLoad
func viewDidLoad()
{
super.viewDidLoad()
listTableView.register(UINib.init(nibName: "ListProductCell", bundle: nil), forCellReuseIdentifier: "ListProductCell")
}
2. Create custom cell this way.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ListProductCell") as! ListProductCell
return cell
}
Swift 5
In same storyboard two class are there Class A and Class B, Class B contains tableview outlet, when i tried to push Class A to Class B it's crashed and show tableView outlet nil.
In class A i did navigation like below code.
let classBObj = ClassB()
self.navigationController?.pushViewController(classBObj, animated: true)
Then i realised my mistake and used below code and it's work perfectly.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let classBObj = storyboard.instantiateViewController(withIdentifier: "ClassB") as! ClassB
self.navigationController?.pushViewController(classBObj, animated: true)
In my case it was the way the Optional is unwrapped:
let cellId:String = "ConverterTableCell"
let cell: ConverterTableViewCell = (tableView.dequeueReusableCellWithIdentifier(cellId)! as? ConverterTableViewCell)!
Try doing this:
let cell = tableView.dequeueReusableCellWithIdentifier("BookCell", forIndexPath: indexPath) as! BookTableViewCell
and don't forget to set the reuse identifier in your storyboard
I am getting this error whenever I use reuse Identifer name different than the custom class name
unifid those names solve it for me
I encounter this error, if I put UITapGestureRecognizer in a custom UITableViewCell on the storyboard.(Xcode version is 8.3).
In Swift 5
First I tried registering my UITableViewCell in viewdidload() using class and identifier which I have mentioned below but it did not work for me.
self.tableView.registerClass(MyCustomTableViewCell.self, forCellReuseIdentifier: "customCell")
Solution
Then I registered my UITableViewCell using Nib name and it worked for me
Register your cell in viewdidload() using Nib name
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.
//register your table view cell in Viewdidload() using Nib Name
tableView.register(UINib.init(nibName: "MyCustomTableViewCell", bundle: nil), forCellReuseIdentifier: "customCell")
}

Resources