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)
      }
    }
  }

}
ShizukaNaHaji
la source
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?

Course B
la source
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.

Aks
la source
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

Jaywant Khedkar
la source
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 :)

MacInnis
la source
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
xhinoda
la source
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é"!)

Anish Parajuli 웃
la source
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")
Peter Honeder
la source
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

Rohit Singh
la source
5

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

tableView.register(UINib(nibName: "YourCellXibName", bundle: nil), forCellReuseIdentifier: "Cell")
ak_ninan
la source
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.

Reza Dehnavi
la source
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"

Scaraux
la source
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")
}
abdos
la source
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()
}
Noor Ali Butt
la source
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

Maria Chen
la source
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.

androCoder-BD
la source
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")
}
swiftBoy
la source
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.

Kai Lean
la source
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.

Vladimir Vodolazkiy
la source