Je voudrais un UITableView
avec des cellules de style subtitle
- qui utilisent dequeueReusableCellWithIdentifier
.
Mon code d'origine Objective-C était:
static NSString* reuseIdentifier = @"Cell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if(!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];
}
Après avoir déjà cherché les quelques questions UITableView
ici sur SO, j'ai pensé l'écrire dans Swift comme suit:
tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: "Cell")
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
Mais cela ne me laisse pas dire que je veux un style subtitle
. Alors j'ai essayé ceci:
var cell :UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell")
Ce qui me donne une cellule subtitle
, mais ne me laisse pas dequeueReusableCellWithIdentifier
.
J'ai fait d'autres recherches et examiné ce didacticiel vidéo , mais il crée un subclass
sur UITableViewCell
distinct, ce qui, je suppose, est inutile, car j'ai déjà réalisé le même effet dans Obj-C.
Des idées? Merci.
Gardez à l'esprit que UITableView
est défini en tant qu'option dans la fonction, ce qui signifie que votre déclaration de cellule initiale doit rechercher l'option dans la propriété. De plus, la cellule en file d'attente renvoyée est également facultative. Veillez donc à effectuer un transtypage facultatif sur UITableViewCell
. Ensuite, nous pouvons forcer le déroulement parce que nous savons que nous avons une cellule.
var cell:UITableViewCell? =
tableView?.dequeueReusableCellWithIdentifier(reuseIdentifier) as? UITableViewCell
if (cell == nil)
{
cell = UITableViewCell(style: UITableViewCellStyle.Subtitle,
reuseIdentifier: reuseIdentifier)
}
// At this point, we definitely have a cell -- either dequeued or newly created,
// so let's force unwrap the optional into a UITableViewCell
cell!.detailTextLabel.text = "some text"
return cell
En gros, la même chose que pour les autres réponses, mais je contourne les options optionnelles (vous ne pouvez pas renvoyer nil
à partir de -tableView:cellForRow:atIndexPath:
dans Swift) en utilisant une variable calculée:
Swift 3
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell = {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell") else {
// Never fails:
return UITableViewCell(style: UITableViewCellStyle.value1, reuseIdentifier: "UITableViewCell")
}
return cell
}()
// (cell is non-optional; no need to use ?. or !)
// Configure your cell:
cell.textLabel?.text = "Key"
cell.detailTextLabel?.text = "Value"
return cell
}
Modifier:
En fait, il serait préférable de retirer la file d'attente de la cellule en utilisant: tableView.dequeueReusableCell(withIdentifier:for:)
à la place.
Cette dernière variante de la fonction instancie automatiquement une nouvelle cellule si personne n’est disponible pour la réutilisation (exactement ce que mon code fait explicitement ci-dessus), et donc never renvoie nil
.
Si vous préférez éviter les options, vous pouvez créer une sous-classe de UITableViewCell qui ressemble à ceci:
class SubtitleTableViewCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Puis enregistrez-le en utilisant:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(SubtitleTableViewCell.self, forCellReuseIdentifier: reuseIdentifier)
}
Cela permet à votre code de personnalisation de cellule d'être vraiment gentil:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath)
cell.textLabel?.text = "foo"
cell.detailTextLabel?.text = "bar"
return cell
}
En partant de la réponse de Memmons, en nettoyant le style Swift 2 ...
let cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier) ?? UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: reuseIdentifier)
cell.detailTextLabel?.text = "some text"
return cell
Swift 3:
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) ?? UITableViewCell(style: .subtitle, reuseIdentifier: cellIdentifier)
cell.detailTextLabel?.text = ""
return cell
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let reuseIdentifier = "cell"
var cell:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier) as UITableViewCell?
if (cell == nil) {
cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: reuseIdentifier)
}
cell!.textLabel?.text = self.items[indexPath.row]
cell!.detailTextLabel?.text = self.items[indexPath.row]
return cell!
}
Puisque tableView.dequeueReusableCell(withIdentifier:, for:)
renvoie une cellule non nulle, la vérification if cell == nil
est toujours fausse . Mais j'ai trouvé une solution: faire en sorte que la cellule de style par défaut devienne le style (valeur1, valeur2 ou sous-titre) souhaité, car la variable de style par défaut detailTextLabel
est nil, vérifiez donc la variable detailTextLabel
si elle est nulle, puis créez une nouvelle cellule de style et attribuez-la à la cellule de la file d'attente, comme suit:
Swift 3:
var cell = tableView.dequeueReusableCell(withIdentifier: yourCellReuseIdentifier, for: indexPath)
if cell.detailTextLabel == nil {
cell = UITableViewCell(style: .value1, reuseIdentifier: repeatCellReuseIdentifier)
}
cell.textLabel?.text = "Title"
cell.detailTextLabel?.text = "Detail"
return cell
Cela fonctionne pour moi.
J'espère que c'est de l'aide.
Vous pouvez utiliser une syntaxe légèrement différente de celle de memmons pour empêcher le déballage forcé:
let cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier) as? UITableViewCell ?? UITableViewCell(style: .Subtitle,
reuseIdentifier: reuseIdentifier)
cell.detailTextLabel?.text = "some text"
return cell
Ceci utilise XCode 6.1 7, rapide 1.2 Syntaxe 2.0 où UITableView
n'est plus une option.
Si vous n'utilisez pas votre propre cellule personnalisée. Enregistrez simplement UITableViewCell via le code. Ensuite, vous pouvez préférer le code.
Sinon, sélectionnez votre storyboard, sélectionnez votre inspecteur d’attributs Goto TableViewCell -> et choisissez le style souhaité, comme indiqué ci-dessous.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath:
NSIndexPath) -> UITableViewCell {
var CellIdentifier:String = "Cell"
var cell:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier(CellIdentifier) as? UITableViewCell
if cell == nil {
cell = UITableViewCell(style:UITableViewCellStyle(rawValue:3)!,reuseIdentifier:CellIdentifier)
}
return cell!
}
Parfait comme suggéré par Michael G. Emmons, mais avec Xcode 6.1 en utilisant
if !cell { .....
Je reçois cette erreur:
Type facultatif '@ | valeur UITableViewCell?' ne peut pas être utilisé comme booléen; test pour '! = nil' à la place
La syntaxe acceptée est la suivante:
if cell == nil { ...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
var cell:UITableViewCell? =
tableView.dequeueReusableCell(withIdentifier: "cell")
if (cell != nil)
{
cell = UITableViewCell(style: UITableViewCellStyle.subtitle,
reuseIdentifier: "cell")
}
cell!.textLabel?.text = "ABC"
cell!.detailTextLabel?.text = "XYZ"
return cell!
}