Swift中的自定义UITableViewCell寄存器类

时间:2014-07-15 06:42:44

标签: uitableview swift ios8

在我的应用程序中,我在数组的基础上填写表格。该表使用自定义UITableViewCell。一切正常,桌子就满了。然后我将搜索显示控制器添加到我的UITableViewController,没有写代码来处理搜索,只需添加控制器。当您运行该应用程序时,该表仍然填充。但如果我尝试单击搜索栏,则会收到错误:

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'

我尝试在UITableViewController行中添加我的viewDidLoad函数:

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

启动应用程序并立即收到错误:

fatal error: unexpectedly found nil while unwrapping an Optional value

排队cell.cellMyCity.text = cellText

我做错了什么?

这是我的Custom UITableViewCell类:

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)

}
}

这是单元格的代码:

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
}

TableViewCell中的属性: enter image description here enter image description here enter image description here

没有self.tableView.registerClass(MyCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)self.tableView.registerClass(MyCell.self, forCellReuseIdentifier: kCellIdentifier)的表:

enter image description here

5 个答案:

答案 0 :(得分:18)

我做的工作是这样的:

class MainViewController: UIViewController {

    // ...

    @IBOutlet var tableView: UITableView

    override func viewDidLoad() {
        super.viewDidLoad()

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

        // ...
    }

    // ...

}

注意:如果我使用 –registerClass(_: forCellReuseIdentifier:) 方法,则不会加载xib文件,因此除非以编程方式添加内容,否则不会显示实际的自定义界面细胞。如果你想从nib文件加载接口,你需要用它的笔尖注册单元格。


符合基本协议:

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
    }

}

并且自定义单元格类是非常通用的,具有有意义的名称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
    }

}

有一个非常随机的界面:

random custom interface

以及自定义类重用标识符的这些设置:

custom class reuse identifier


并且我的屏幕上的最终结果是我预期的3行:

the final result in practice

注意:要进一步自定义自定义单元格,您可能需要扩展上面的代码。

更新

UISearchBar,最终结果如下:

with Search Bar

答案 1 :(得分:10)

self之前添加tableView解决问题:

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

答案 2 :(得分:8)

由于错误提示您的cellUITestField nilSwift不支持对nil对象的方法调用,这就是为什么你正在崩溃。你可以通过检查对象是否为nil来防止崩溃

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

修改

我想我在这里遇到了什么问题......

您已在UISearchBar中拖放storyboard,因此默认设置为控制器的所有数据源和委托代表ViewController(在其中覆盖UITableView DataSource方法的类)并在ViewController中注册MyCell类作为自定义类。 所以你的tableView显示完美但是当你输入UISearchBar的东西时,同样调用了相同的DataSource方法(ViewController),你为searchResultsTableView注册MyCell(UISearchDisplayController tableView显示搜索结果) ,但这并不了解MyCell以及为什么cell.cellMyCity在搜索时为零的原因,这意味着searchResultsTableView期望默认UITableViewCell而你是不为默认单元格设置任何内容,如 -

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

您可以通过将DataSource方法更改为

来观察整个场景
    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
}

解决方案而言而言,可能有两种可能的解决方案..

A)。请勿使用searchResultsTableView(由UISearchDisplayController提供),并将您的搜索结果显示在与tableView相同的ViewController中。为此你可以做的是 - 当用户在UISearchBar中键入一些东西时,听取UISearchBar个委托,通过谓词和显示结果得到你的结果数据源(可能在不同的数组中){{1 }}

B)。自定义UISearchDisplayController并在UITableView

中使用您的自定义单元格(即MyCell)

答案 3 :(得分:2)

如果您使用的是故事板,请务必删除注册类,因为它会覆盖故事板以及与之关联的所有外链

请检查 https://stackoverflow.com/a/26350795/4453583

它对我有用=)

答案 4 :(得分:1)

您必须记住为任何使用它的tableView注册单元格 - 包括searchDisplayController.tableView。