Custom UITableViewCell register class in Swift

孤街浪徒 提交于 2020-01-10 01:02:50

问题


In my application, I fill the table on the basis of the array. The table uses custom UITableViewCell. Everything works fine, table is filled. Then I add Search Display Controller to my UITableViewController, no write code to handle the search, simply add the controller. When you run the application, the table is still filled.But if I try to click on the search bar, I get the error:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier CitiesListCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'

I try to add to my viewDidLoad function in UITableViewController line:

self.tableView.registerClass(MyCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)

Launch the application and immediately get the error:

fatal error: unexpectedly found nil while unwrapping an Optional value

In line cell.cellMyCity.text = cellText

What am I doing wrong?

This is my Custom UITableViewCell class:

import UIKit

class MyCell: UITableViewCell {

@IBOutlet var cellMyImage: UIImageView
@IBOutlet var cellMyCity: UILabel
@IBOutlet var cellMyCountry: UILabel
@IBOutlet var cellMyTemp: UILabel

init(style: UITableViewCellStyle, reuseIdentifier: String!) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
}

override func awakeFromNib() {
    super.awakeFromNib()
}

override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

}
}

This is code for cell:

override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {

    var cell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier, forIndexPath: indexPath) as MyCell!

    if cell == nil {
        cell = MyCell(style: UITableViewCellStyle.Default, reuseIdentifier: kCellIdentifier)
    }

    let cellText: String? = dataWeatherSelectedCity[indexPath.row].name as  String
    println("Строка: \(cellText)")
    cell.cellMyCity.text = cellText

    let cellSubtitle: String? = dataWeatherSelectedCity[indexPath.row].country as String
    cell.cellMyCountry.text = cellSubtitle

    cell.cellMyImage.image = UIImage(named: "Blank52")

    var currentCityWeatherURL = "http://api.wunderground.com/api/\(self.myAPI.kWundergroundApiKey)/conditions/lang:RU/q/zmw:\(self.dataWeatherSelectedCity[indexPath.row].zmv).json"

    var fullObservation:NSDictionary = self.myAPI.jsonParsingWeather(currentCityWeatherURL)
    var currentObservation:NSDictionary = fullObservation.valueForKey("current_observation") as NSDictionary

    var currentWeather = self.myAPI.parsingOneCityCurrentCondition(currentObservation)       
    cell.cellMyImage.image = currentWeather.image
    cell.cellMyTemp.text = currentWeather.temp
    return cell
}

Property in TableViewCell:

Table without self.tableView.registerClass(MyCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier) or self.tableView.registerClass(MyCell.self, forCellReuseIdentifier: kCellIdentifier):


回答1:


As error suggest you are getting your cell or UITestField nil and Swift doesn't support method call on nil object that's why you are getting crash. you can prevent crash by checking the object is nil or not as bellow

if var label = cell.cellMyCity{
    label.text = cellText
}

EDIT

I think I got what is the problem here...

You have drag-n-drop UISearchBar in your storyboard, So by defaults all data source and delegate set to your Controller say, ViewController(class in which you override UITableView DataSource methods) and in that ViewController you register MyCell class as your customize class. So your tableView displays perfect but when you type something to UISearchBar, same DataSource methods (ViewController) called and there as well, you registers MyCell for searchResultsTableView (UISearchDisplayController tableView thats display search result), but that doesn't know about MyCell and that's why cell.cellMyCity is coming as nil in case of search, that means searchResultsTableView expect the default UITableViewCell and you are not setting anything for default cell like -

cell.textLabel.text = countryList[indexPath.row]

this whole scenario you can observe by changing you DataSource methods as bellow

    override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {

    var cell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) as MyCell!
    if cell == nil {
        //tableView.registerNib(UINib(nibName: "UICustomTableViewCell", bundle: nil), forCellReuseIdentifier: "UICustomTableViewCell")
        tableView.registerClass(MyCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)

        cell = MyCell(style: UITableViewCellStyle.Default, reuseIdentifier: kCellIdentifier)
    }
    if var label = cell.cellMyCity{
        label.text = countryList[indexPath.row]
    }
    else{
        cell.textLabel.text = countryList[indexPath.row]
    }
    return cell
}

As far as Solution is concern, there could be two possible solution..

A). Don't use searchResultsTableView (provided by UISearchDisplayController) and display your search results in the same tableView that you have in your ViewController. For that what you can do is - listen to the UISearchBar delegates when user type some thing in UISearchBar get your result datasource (May be in different array) by Predicates and Display results in the same UITableView.

B). Customize UISearchDisplayController and use your custom cell (i.e MyCell) in searchResultsTableView




回答2:


what I did for making that working is something like this:

class MainViewController: UIViewController {

    // ...

    @IBOutlet var tableView: UITableView

    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.registerNib(UINib(nibName: "UICustomTableViewCell", bundle: nil), forCellReuseIdentifier: "UICustomTableViewCell")

        // ...
    }

    // ...

}

NOTE: If I use the –registerClass(_: forCellReuseIdentifier:) method, the xib file won't be loaded, therefore the actual custom interface will not appear unless you add the content programatically to the cell. if you'd like to load the interface from a nib file, you need to register the cell with its nib.


conforming the essential protocols:

extension MainViewController: UITableViewDataSource {

    func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
        let cell: UICustomTableViewCell = tableView.dequeueReusableCellWithIdentifier(UICustomTableViewCell.reuseIdentifier) as UICustomTableViewCell
        println(cell)
        return cell;
    }

}

//

extension MainViewController: UITableViewDelegate {

    func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
        return 44.0
    }

}

and the custom cell class was a very generic one with a meaningful name as UICustomTableViewCell:

class UICustomTableViewCell: UITableViewCell {

    class var reuseIdentifier: String {
        get {
            return "UICustomTableViewCell"
        }
    }

    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
    }

}

with a quite random interface:

and these settings of custom class and reuse identifier:


and the final result on my screen is as I expected with 3 rows:

NOTE: for further customisation of the custom cells you may need extend the code above.

UPDATE

with UISearchBar, the final result would be like this:




回答3:


Adding self before tableView fixes the issues:

var cell = self.tableView.dequeueReusableCellWithIdentifier(kCellIdentifier, forIndexPath: indexPath) as MyCell!



回答4:


make sure to remove register class if you are using storyboard as it will overwrite the storyboard and all the outlink associated with it

please check https://stackoverflow.com/a/26350795/4453583

it works for me =)




回答5:


You must remember to register the cell for any tableView that use it -- including searchDisplayController.tableView.



来源:https://stackoverflow.com/questions/24751513/custom-uitableviewcell-register-class-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!