Пользовательский класс регистров UITableViewCell в Swift

В моем приложении я заполняю таблицу на основе массива. В таблице используется пользовательский UITableViewCell. Все работает нормально, стол заполнен. Затем я добавляю Search Display Controller в свой 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'

Я пытаюсь добавить к моей функции viewDidLoad в строке UITableViewController:

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

Запустите приложение и немедленно получите сообщение об ошибке:

fatal error: unexpectedly found nil while unwrapping an Optional value

В строке cell.cellMyCity.text = cellText

Что я делаю неправильно?

Это мой пользовательский класс 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 hereenter image description hereenter image description here

Таблица без self.tableView.registerClass(MyCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier) или self.tableView.registerClass(MyCell.self, forCellReuseIdentifier: kCellIdentifier):

enter image description here

Ответы

Ответ 1

Как подсказывает ошибка, вы получаете свои cell или UITestField nil и Swift не поддерживает вызов метода на объекте nil, почему вы получаете сбой. вы можете предотвратить сбой, проверяя, что объект равен нулю или ниже, чем ниже.

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

ИЗМЕНИТЬ

Я думаю, что у меня есть проблема здесь...

У вас есть drag-n-drop UISearchBar в storyboard, поэтому по умолчанию все источник данных и делегат, установленные вашим контроллером, говорят, ViewController (класс, в котором вы переопределяете UITableView DataSource), и в этом ViewController вы регистрируете класс MyCell как свой класс настройки. Таким образом, ваш TableView отображается идеально, но когда вы вводите что-то в UISearchBar, вызываете те же методы DataSource (ViewController), и вы регистрируете MyCell для searchResultsTableView (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
}

Что касается Решение проблемы, может быть два возможных решения.

А). Не используйте searchResultsTableView (предоставляется UISearchDisplayController) и покажите результаты поиска в том же tableView, который у вас есть в ViewController. Для этого вы можете сделать это - прослушать делегатов UISearchBar, когда пользователь вводит что-то в UISearchBar, чтобы получить исходный источник данных (может быть в другом массиве) с помощью Predicates и Display в том же UITableView.

В). Настройте UISearchDisplayController и используйте свою пользовательскую ячейку (например, MyCell) в searchResultsTableView

Ответ 2

то, что я сделал для создания этой работы, выглядит примерно так:

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, вам необходимо зарегистрировать ячейку со своим 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 classreuse identifier


и конечный результат на моем экране, как я ожидал, с тремя строками:

the final result in practice

ПРИМЕЧАНИЕ. Для дальнейшей настройки пользовательских ячеек вам может потребоваться расширить код выше.

UPDATE

с UISearchBar, конечный результат будет таким:

with Search Bar

Ответ 3

Добавление self до tableView устраняет проблемы:

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

Ответ 4

Вы должны помнить о регистрации ячейки для любого используемого ею tableView, включая searchDisplayController.tableView.

Ответ 5

обязательно удалите класс регистра, если вы используете раскадровку, поскольку она перезапишет раскадровку и всю связанную с ней связь

проверьте fooobar.com/info/6705/...

он работает для меня =)