Dans mon application, je remplis la table sur la base du tableau. La table utilise UITableViewCell personnalisé. Tout fonctionne bien, la table est remplie. Ensuite, j'ajoute un contrôleur d'affichage de recherche à mon UITableViewController, aucun code en écriture pour gérer la recherche, il suffit d'ajouter le contrôleur. Lorsque vous exécutez l'application, la table est toujours remplie. Mais si j'essaie de cliquer sur la barre de recherche, j'obtiens le message d'erreur suivant:
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'
J'essaie d'ajouter à ma fonction viewDidLoad dans la ligne UITableViewController:
self.tableView.registerClass(MyCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)
Lancez l'application et obtenez immédiatement l'erreur:
fatal error: unexpectedly found nil while unwrapping an Optional value
En ligne cell.cellMyCity.text = cellText
Qu'est-ce que je fais mal?
Ceci est ma classe personnalisée 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)
}
}
C'est le code de la cellule:
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
}
Propriété dans TableViewCell:
Table sans self.tableView.registerClass(MyCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)
ou self.tableView.registerClass(MyCell.self, forCellReuseIdentifier: kCellIdentifier)
:
Comme le suggère l’erreur, vous obtenez votre cell
ou UITestField
nil
et Swift
ne prend pas en charge l’appel de méthode sur un objet nil, c’est la raison pour laquelle vous obtenez un crash. vous pouvez empêcher le crash en vérifiant que l'objet est nul ou non comme ci-dessous
if var label = cell.cellMyCity{
label.text = cellText
}
MODIFIER
Je pense que j'ai quel est le problème ici ...
Vous avez un glisser-déposer UISearchBar
dans votre storyboard
, ainsi, par défaut, toutes les sources de données et le délégué sont définis sur votre contrôleur. Par exemple, ViewController
(classe dans laquelle vous écrasez les méthodes UITableView DataSource) et ViewController
vous enregistrez la classe MyCell comme votre classe de personnalisation . Ainsi, votre tableView affiche parfaitement, mais lorsque vous tapez quelque chose dans UISearchBar, les mêmes méthodes DataSource (ViewController
) sont appelées et là aussi, vous enregistrez MyCell pour searchResultsTableView
(UISearchDisplayController
tableView qui affiche le résultat de la recherche), mais cela ne signifie Si vous ne connaissez pas MyCell, c’est pourquoi cell.cellMyCity
est nul en cas de recherche; cela signifie que searchResultsTableView
s’attend à la valeur par défaut UITableViewCell
et que vous ne définissez rien comme cellule par défaut -
cell.textLabel.text = countryList[indexPath.row]
tout ce scénario que vous pouvez observer en changeant vos méthodes DataSource comme ci-dessous
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
}
En ce qui concerne La solution concerne, il pourrait y avoir deux solutions possibles.
UNE). N'utilisez pas searchResultsTableView
(fourni par UISearchDisplayController
) et affichez vos résultats de recherche dans la même tableView
que vous avez dans votre ViewController
. Pour cela, écoutez les délégués UISearchBar
lorsque l'utilisateur saisit quelque chose dans UISearchBar
obtenir votre source de données de résultats (peut être dans un tableau différent) par Prédicats et afficher les résultats dans la même UITableView
.
B) Personnalisez UISearchDisplayController et utilisez votre cellule personnalisée (i.e MyCell) dans searchResultsTableView
ce que j'ai fait pour que cela fonctionne ressemble à ceci:
class MainViewController: UIViewController {
// ...
@IBOutlet var tableView: UITableView
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.registerNib(UINib(nibName: "UICustomTableViewCell", bundle: nil), forCellReuseIdentifier: "UICustomTableViewCell")
// ...
}
// ...
}
REMARQUE: Si j'utilise la méthode –registerClass(_: forCellReuseIdentifier:)
, le fichier xib ne sera pas chargé. Par conséquent, l'interface personnalisée réelle n'apparaîtra que si vous ajoutez le contenu par programme à la cellule. si vous souhaitez charger l'interface à partir d'un fichier nib, vous devez enregistrer la cellule avec son nib.
conforme aux protocoles essentiels:
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
}
}
et la classe de cellules personnalisée était une classe très générique avec un nom significatif comme 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
}
}
avec une interface assez aléatoire:
et ces paramètres de classe personnalisée et identifiant de réutilisation :
et le résultat final sur mon écran est comme je m'y attendais avec 3 lignes:
REMARQUE: pour personnaliser davantage les cellules personnalisées, vous devrez peut-être étendre le code ci-dessus.
avec UISearchBar
, le résultat final serait le suivant:
L'ajout de self
avant tableView
résout les problèmes suivants:
var cell = self.tableView.dequeueReusableCellWithIdentifier(kCellIdentifier, forIndexPath: indexPath) as MyCell!
assurez-vous de supprimer la classe register si vous utilisez le storyboard car il écrasera le storyboard et tous les liens externes qui lui sont associés.
veuillez vérifier https://stackoverflow.com/a/26350795/4453583
ça marche pour moi =)
N'oubliez pas d'enregistrer la cellule pour toute tableView l'utilisant, y compris searchDisplayController.tableView.