Пользовательский класс регистров 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 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]()
Ответы
Ответ 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 class]()
![reuse 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/...
он работает для меня =)