iosswiftuitableviewios8.3

Register Nib/Class cell crash on iOS 8.3


I have used the following code in viewDidLoad to register nib cell :

tableView.register(UINib(nibName: "ShoppingViewCell", bundle: Bundle.main), forCellReuseIdentifier: "ShoppingViewCell")

And in cellForRowAtIndexPath I use the following for cell:

let cell = self.tableView.dequeueReusableCell(withIdentifier: "ShoppingViewCell", for: indexPath) as! ShoppingViewCell

return cell

But Sadly this only works with IOS 9 and up, trying to run this code on iOS 8.3 crashes with following error :

2016-09-27 14:17:04.859 Tazaj[29070:1917376] *** Assertion failure in -[UITableView dequeueReusableCellWithIdentifier:forIndexPath:], /SourceCache/UIKit_Sim/UIKit-3347.44/UITableView.m:6245
2016-09-27 14:17:04.877 Tazaj[29070:1917376] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier ShoppingViewCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'

Since register nib and dequeueReusableCell is already found since iOS 5/6, why its not working on iOS 8.3.

I know that by running the following code in cellForRowAtIndex will solve the issue :

    var mycell = tableView.dequeueReusableCell(withIdentifier: "ShoppingViewCell") as? ShoppingViewCell

    if (mycell == nil) {

        mycell = Bundle.main.loadNibNamed("ShoppingViewCell", owner: nil, options: nil)?.last as? ShoppingViewCell

    }

But I have builded a whole project without check that cell is nil or not. I mean how can I solve the issue ? since apple said register cell and use the cell the way you want, I did it. so why only in iOS 8.x/8.3 it cannot work ?

How is it possible to ignore/fix that error with least replacing chunks of code in each cellForRowAtIndexPath ?


Solution

  • Just put this method in your custom cell class

    class func cellForTableView(tableView: UITableView, atIndexPath indexPath: NSIndexPath) -> ShoppingViewCell {
        let kShoppingViewCellIdentifier = "kShoppingViewCellIdentifier"
        tableView.registerNib(UINib(nibName: "ShoppingViewCell", bundle: NSBundle.mainBundle()), forCellReuseIdentifier: kShoppingViewCellIdentifier)
        let cell = tableView.dequeueReusableCellWithIdentifier(kShoppingViewCellIdentifier, forIndexPath: indexPath) as! ShoppingViewCell
        return cell
    }
    

    And use it lieke below in your cellForRowAtIndexPath

    let cell = ShoppingViewCell.cellForTableView(tableView, atIndexPath: indexPath)
    // do something with your cell
    

    I hope it helps.

    Update for Swift 3 and Swift 4

    class func cellForTableView(tableView: UITableView, atIndexPath indexPath: IndexPath) -> YourCustomTableViewCell {
        let kYourCustomTableViewCellIdentifier = "kYourCustomTableViewCellIdentifier"
        tableView.register(UINib(nibName: "YourCustomTableViewCell", bundle: Bundle.main), forCellReuseIdentifier: kYourCustomTableViewCellIdentifier)
        let cell = tableView.dequeueReusableCell(withIdentifier: kYourCustomTableViewCellIdentifier, for: indexPath) as! YourCustomTableViewCell
        return cell
    }