impossible de retirer une cellule avec l'identifiant Cell - doit enregistrer une pointe ou une classe pour l'identifiant ou connecter une cellule prototype dans un storyboard


114

Je suis assez nouveau dans le codage en général et vraiment nouveau sur Xcode (Swift). Je comprends que j'ai besoin d'enregistrer une plume ou une classe mais je ne comprends pas «où ni comment?».

import UIKit

class NotesListViewController: UITableViewController {

    @IBOutlet weak var menuButton: UIBarButtonItem!

  override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self,
      selector: "preferredContentSizeChanged:",
      name: UIContentSizeCategoryDidChangeNotification,
      object: nil)

    // Side Menu

    if self.revealViewController() != nil {
        menuButton.target = self.revealViewController()
        menuButton.action = "revealToggle:"
        self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }

  }

  override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    // whenever this view controller appears, reload the table. This allows it to reflect any changes
    // made whilst editing notes
    tableView.reloadData()
  }

  func preferredContentSizeChanged(notification: NSNotification) {
    tableView.reloadData()
  }

  // #pragma mark - Table view data source

  override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
  }

  override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return notes.count
  }

  override func tableView(tableView: UITableView, cellForRowAtIndexPath   indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell

    let note = notes[indexPath.row]
    let font = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)
    let textColor = UIColor(red: 0.175, green: 0.458, blue: 0.831, alpha: 1)
    let attributes = [
      NSForegroundColorAttributeName : textColor,
      NSFontAttributeName : font,
      NSTextEffectAttributeName : NSTextEffectLetterpressStyle
    ]
    let attributedString = NSAttributedString(string: note.title, attributes: attributes)

    cell.textLabel?.font = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)

    cell.textLabel?.attributedText = attributedString

    return cell
  }

  let label: UILabel = {
    let temporaryLabel = UILabel(frame: CGRect(x: 0, y: 0, width: Int.max, height: Int.max))
    temporaryLabel.text = "test"
    return temporaryLabel
    }()

  override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    label.font = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)
    label.sizeToFit()
    return label.frame.height * 1.7
  }

  override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == .Delete {
      notes.removeAtIndex(indexPath.row)
      tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
    }
  }

  // #pragma mark - Navigation

  // In a storyboard-based application, you will often want to do a little preparation before navigation
  override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if let editorVC = segue.destinationViewController as? NoteEditorViewController {

      if "CellSelected" == segue.identifier {
        if let path = tableView.indexPathForSelectedRow() {
          editorVC.note = notes[path.row]
        }
      } else if "AddNewNote" == segue.identifier {
        let note = Note(text: " ")
        editorVC.note = note
        notes.append(note)
      }
    }
  }

}

11
Méfiez-vous du déroutant "ID de restauration" - qui n'est rien! Cliquez sur le QUATRIÈME onglet en haut à droite, PAS sur le TROISIÈME onglet !!
Fattie

Réponses:


82

Avez-vous défini l' identificateur de cellule de tableau sur "Cellule" dans votre storyboard?

Ou avez-vous défini la classe pour UITableViewControllervotre classe dans cette scène?


102

Vous pouvez enregistrer une classe pour votre UITableViewCellcomme ceci:

Avec Swift 3+:

self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")

Avec Swift 2.2:

self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")

Assurez-vous que le même identifiant " cell" est également copié dans votre storyboard UITableViewCell.

" self" sert à faire en sorte que la classe utilise le nom de la classe suivi de .self.


1
Où mettez-vous cela?
RJB

7
dans viewDidLoad()
Mette

18
Si vous utilisez un xib dans votre cellule personnalisée, vous devrez l'enregistrer comme ceci:tableView.register(UINib.init(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "CustomCellIdentifier")
atulkhatri

la solution swift 3+ ci-dessus a fonctionné pour moi dans swift 5
Mike Volmar

38

Cela a fonctionné pour moi, peut vous aider aussi:

Swift 4+:

self.tableView.register(UITableViewCell.self, forCellWithReuseIdentifier: "cell")

Swift 3 :

self.tableView.register(UITableViewCell.classForKeyedArchiver(), forCellReuseIdentifier: "Cell")

Swift 2.2 :

self.tableView.registerClass(UITableViewCell.classForKeyedArchiver(), forCellReuseIdentifier: "Cell")

Nous devons définir la propriété Identifier sur Table View Cell selon l'image ci-dessous,

entrez la description de l'image ici


1
Just so simple :-)
Luc-Olivier

1
ça a marché! J'étais en train de définir l'ID dans l'inspecteur d'identité, mais le coller dans l'inspecteur d'attributs a fonctionné pour moi
Fato

1
Dieu te bénisse! J'ai sauvé un couple de ma vie
Ragen Dazs le

26

J'ai eu ce problème aujourd'hui qui a été résolu en sélectionnant Produit -> Nettoyer. J'étais tellement confus car mon code était correct. Le problème a commencé en utilisant trop souvent la commande-Z :)


1
Sérieusement passé plus d'une heure à essayer de déboguer cela. Merci :)
réveillé le

Bien sûr, cela fonctionne en combinaison avec la définition de l'identifiant dans le storyboard (voir la réponse suivante)
Nech

21

y mon cas, j'ai résolu ce problème en le nommant dans la propriété "Identifier" de la cellule de vue tableau:

entrez la description de l'image ici

N'oubliez pas: à déclarer dans votre classe: UITableViewDataSource

 let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell

cette image ne correspond pas mais elle a donné un indice.
Martian2049

c'est un peu dépassé juste
Martian2049

13

Faites simplement glisser une cellule (comme vous l'avez fait pour TableViewController) et ajoutez-y simplement en libérant la cellule sur TableViewController. Cliquez sur la cellule et allez à son inspecteur d'attributs et définissez son identifiant comme "Cellule". J'espère que cela fonctionne.


N'oubliez pas que vous voulez un identifiant sur l' inspecteur d'attributs .

( PAS le "ID de restauration" sur "l'inspecteur d'identité"!)


6
Méfiez-vous du déroutant "ID de restauration" - qui n'est rien! Cliquez sur le QUATRIÈME onglet en haut à droite, PAS sur le TROISIÈME onglet !!!
Fattie

9

Une autre raison pour laquelle ce problème se produit est un problème antérieur. Lors de l'affichage d'un nouveau ViewController, l'instanciation directe du ViewController cible ne chargera bien sûr pas les cellules prototypes du StoryBoard. La solution correcte doit toujours être d'instancier le contrôleur de vue via le storyboard comme ceci:

storyboard?.instantiateViewController(withIdentifier: "some_identifier")

Oui!! C'est vrai!! Cela m'est arrivé parce que je suis passé au ViewController qui se trouve dans un autre Storyboard juste avec: self.present (MyViewController, animé: faux, complétion: nil). Et il semble qu'il ne télécharge vraiment pas le prototype! J'ai essayé de démarrer directement avec MyViewController et cela fonctionne bien! Cela fonctionne également lorsque j'enregistre NIB pour ma cellule dans viewDidLoad de la cible ViewController.
Vitya Shurapov

7

Faites correspondre le nom de l'identifiant aux deux endroits

Cette erreur se produit lorsque le nom d'identificateur de la table est différent dans le fichier Swift et dans le Storyboard.

Par exemple, l'identifiant est placecellIdentifier dans mon cas.

1) Le fichier Swift

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "placecellIdentifier", for: indexPath)

    // Your code 

    return cell
}

2) Le Storyboard

entrez la description de l'image ici


5

Dans Swift 3.0, enregistrez une classe pour votre UITableViewCell comme ceci:

tableView.register(UINib(nibName: "YourCellXibName", bundle: nil), forCellReuseIdentifier: "Cell")

2

J'ai eu le même problème. Ce problème a fonctionné pour moi. Dans le storyboard, sélectionnez votre vue de tableau et changez-la de cellules statiques en cellules dynamiques.


2

Si vous avez défini votre cellule via Interface Builder, en plaçant une cellule à l'intérieur de votre UICollectionView, ou UITableView:

Assurez-vous que vous avez lié la cellule avec une classe réelle que vous avez créée, et très important, que vous avez coché "Hériter le module de la cible"


2

Il fonctionnait auparavant sur Swift 3 et Swift 4, mais maintenant il ne fonctionne pas.

comme

self.tableView.register(MyTestTableViewCell.self, forCellReuseIdentifier: "cell")

J'ai donc essayé la plupart des solutions mentionnées ci-dessus dans swift 5 mais je n'ai pas eu de chance.

Enfin, j'ai essayé cette solution et cela a fonctionné pour moi.

override func viewDidLoad() 
{

    tableView.register(UINib.init(nibName: "MyTestTableViewCell", bundle: nil), forCellReuseIdentifier: "myTestTableViewCell")
}

2

Mon problème était que j'enregistrais de manière asynchrone la cellule de vue de la table dans la file d'attente de distribution. Si vous avez enregistré la source de vue de table et délégué la référence dans le storyboard, la file d'attente de distribution retarderait l'enregistrement de la cellule car le nom le suggère, cela se produira de manière asynchrone et votre vue de table recherche les cellules.

DispatchQueue.main.async {
    self.tableView.register(CampaignTableViewCell.self, forCellReuseIdentifier: CampaignTableViewCell.identifier())
    self.tableView.reloadData()
}

Soit vous ne devez pas utiliser la file d'attente de répartition pour l'enregistrement, soit procédez comme suit:

DispatchQueue.main.async {
    self.tableView.dataSource = self
    self.tableView.delegate = self
    self.tableView.register(CampaignTableViewCell.self, forCellReuseIdentifier: CampaignTableViewCell.identifier())
    self.tableView.reloadData()
}

1

Je viens de rencontrer le même problème et voir ce post. Pour moi, c'est parce que j'ai oublié l'ensemble de l'identifiant de la cellule, également comme mentionné dans d'autres réponses. Ce que je veux dire, c'est que si vous utilisez le storyboard pour charger une cellule personnalisée, nous n'avons pas besoin d'enregistrer la cellule de vue de tableau dans le code, ce qui peut causer d'autres problèmes.

Voir cet article pour plus de détails:

Cellule de vue de tableau personnalisée: l'étiquette IBOutlet est nulle


0

Juste pour les nouveaux amis iOS (comme moi) qui ont décidé d'avoir plusieurs cellules et dans un fichier xib différent, la solution n'est pas d'avoir un identifiant mais de faire ceci:

let cell = Bundle.main.loadNibNamed("newsDetails", owner: self, options: nil)?.first as! newsDetailsTableViewCell

ici newsDetails est le nom du fichier xib.


0

Swift 5

vous devez utiliser la méthode UINib pour enregistrer la cellule dans viewDidLoad

override func viewDidLoad() 
{
    super.viewDidLoad()
    // Do any additional setup after loading the view.

    //register table view cell        
    tableView.register(UINib.init(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "CustomTableViewCell")
}

0

Dans le champ «Sous-classe de», sélectionnez UITableViewController.

Le titre de la classe devient xxxxTableViewController. Laissez cela tel quel.

Assurez-vous que l'option «Créer également un fichier XIB» est sélectionnée.


0

Je suis tombé sur ce message lorsque UITableView dans l'IB a été déplacé dans une autre sous-vue avec Cmd-C - Cmd-V.

Tous les identifiants, méthodes de délégué, liens dans l'IB, etc. restent intacts, mais une exception est déclenchée au moment de l'exécution.

La seule solution est d'effacer toutes les encres, liées à la vue de table dans l'IB (sortie, source de données, délégué) et de les refaire.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.