web-dev-qa-db-fra.com

Comment définir UITableViewCellStyleSubtitle et dequeueReusableCell dans Swift?

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.

37
user3127576

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
63
memmons

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.

19
Nicolas Miari

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
}
13
Jeremy Massel

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
10
jonlambert
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!
}
5
Geoffrey

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.

3
Meilbn

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.

2
lammert

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. 

 enter image description here

1
Sudhi 9135
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!
}
0
Amit Jagesha シ

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 { ...
0
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!

  }
0
iOS Lifee