incapaz de retirar da fila uma célula com o identificador Cell - deve registrar um bico ou uma classe para o identificador ou conectar uma célula protótipo em um storyboard

114

Eu sou bastante novo na codificação em geral e muito novo no Xcode (Swift). Eu entendo que preciso registrar um bico ou uma classe, mas não entendo 'onde ou como?'.

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
fonte
11
Cuidado com o confuso "ID de restauração" - que não é nada! Clique na QUARTA guia no canto superior direito, NÃO na TERCEIRA guia !!
Fattie

Respostas:

82

Você definiu o identificador Table Cell como "Cell" em seu storyboard?

Ou você definiu a classe para a UITableViewControllersua classe nessa cena?

Corrida B
fonte
102

Você pode registrar uma aula para o seu UITableViewCell como este:

Com Swift 3+:

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

Com Swift 2.2:

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

Certifique-se de que o mesmo identificador " cell" também seja copiado no seu storyboardUITableViewCell .

" self" é para obter a classe, use o nome da classe seguido por .self.

Aks
fonte
1
Onde você coloca isso?
RJB
7
in viewDidLoad()
Mette
18
Se você estiver usando um xib em seu celular personalizado, você terá que registrá-lo assim:tableView.register(UINib.init(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "CustomCellIdentifier")
atulkhatri
a solução 3+ swift acima funcionou para mim no swift 5
Mike Volmar
38

Isso funcionou para mim, pode ajudá-lo também:

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

Temos que definir a propriedade Identifier para Table View Cell conforme a imagem abaixo,

insira a descrição da imagem aqui

Jaywant Khedkar
fonte
1
Simplesmente tão simples :-)
Luc-Olivier
1
funcionou! Eu estava definindo o ID no inspetor de identidade, mas colá-lo no inspetor de atributos funcionou para mim
Fato
1
Deus te abençoê! Salvou um par da minha vida
Ragen Dazs
26

Tive esse problema hoje que foi resolvido selecionando Produto -> Limpar. Eu estava tão confuso, já que meu código era adequado. O problema começou com o uso de command-Z muitas vezes :)

MacInnis
fonte
1
Sério, passei mais de uma hora tentando depurar isso. Obrigado :)
despertou em
Claro que funciona em combinação com a definição do identificador no storyboard (veja a próxima resposta)
Nech
21

No meu caso, resolvi isso nomeando-o na propriedade "Identifier" da Table View Cell:

insira a descrição da imagem aqui

Não se esqueça: para declarar em sua classe: UITableViewDataSource

 let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell
xhinoda
fonte
esta imagem é incompatível, mas deu alguma dica.
Martian2049,
está um pouco desatualizado
Martian2049
13

Basta arrastar uma célula (como você fez para TableViewController) e adicioná-la apenas liberando a célula em TableViewController. Clique na célula e. Vá para o inspetor de atributos e defina seu identificador como "Célula". Espero que funcione.


Não se esqueça de que você deseja o Identificador no Inspetor de atributos .

( NÃO o "ID de restauração" no "Inspetor de identidade"!)

Anish Parajuli 웃
fonte
6
Cuidado com o confuso "ID de restauração" - que não é nada! Clique na QUARTA aba no canto superior direito, NÃO na TERCEIRA aba !!!
Fattie
9

Mais uma razão para esse problema acontecer é um problema anterior. Ao mostrar um novo ViewController, instanciar o ViewController de destino diretamente, obviamente, não carregará as células de protótipo do StoryBoard. A solução correta deve ser sempre instanciar o controlador de visualização por meio do storyboard como este:

storyboard?.instantiateViewController(withIdentifier: "some_identifier")
Peter Honeder
fonte
Sim!! É verdade!! Isso aconteceu comigo porque eu fiz a transição para o ViewController que está localizado em um Storyboard diferente apenas com: self.present (MyViewController, animado: falso, conclusão: nulo). E parece que realmente não faz o download do protótipo! Eu tentei começar com MyViewController diretamente e funciona direito! Também funciona quando estou registrando o NIB para minha célula em viewDidLoad do ViewController de destino.
Vitya Shurapov
7

Combine o nome do identificador em ambos os lugares

Este erro ocorre quando o nome do identificador da Tablecell é diferente no arquivo Swift e no Storyboard.

Por exemplo, o identificador é placecellIdentifier no meu caso.

1) O Arquivo Swift

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

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

    // Your code 

    return cell
}

2) O Storyboard

insira a descrição da imagem aqui

Rohit Singh
fonte
5

No Swift 3.0, registre uma classe para seu UITableViewCell como esta:

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

Eu tive o mesmo problema. Esse problema funcionou para mim. No storyboard, selecione a visualização da tabela e mude de células estáticas para células dinâmicas.

Reza Dehnavi
fonte
2

Se você definiu sua célula por meio do Interface Builder, colocando uma célula dentro de sua UICollectionView, ou UITableView:

Certifique-se de vincular a célula com uma classe real que você criou, e muito importante, que você marcou "Herdar módulo do destino"

Scaraux
fonte
2

Ele costumava funcionar no swift 3 e no swift 4, mas agora não está funcionando.

gostar

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

Portanto, tentei a maioria das soluções mencionadas acima no swift 5, mas não tive sorte.

Finalmente tentei essa solução e funcionou para mim.

override func viewDidLoad() 
{

    tableView.register(UINib.init(nibName: "MyTestTableViewCell", bundle: nil), forCellReuseIdentifier: "myTestTableViewCell")
}
abdômen
fonte
2

Meu problema era que eu estava registrando a célula do table view dentro da fila de despacho de forma assíncrona. Se você registrou a fonte de exibição de tabela e a referência de delegado no storyboard, a fila de despacho atrasaria o registro da célula, pois o nome sugere que isso acontecerá de forma assíncrona e sua exibição de tabela está procurando as células.

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

Ou você não deve usar a fila de despacho para registro OU fazer isto:

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
fonte
1

Acabei de encontrar o mesmo problema e ver este post. Para mim é porque esqueci o conjunto do identificador de celular, também como mencionei nas outras respostas. O que eu quero dizer é que se você estiver usando o storyboard para carregar a célula customizada, não precisamos registrar a célula de visualização de tabela no código, o que pode causar outros problemas.

Veja esta postagem para detalhes:

Célula de visualização de tabela personalizada: o rótulo IBOutlet é nulo

Maria chen
fonte
0

Apenas para aqueles novos amigos iOS (como eu) que decidiram ter várias células e em um arquivo xib diferente, a solução não é ter identificador, mas fazer isso:

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

aqui, newsDetails é o nome do arquivo xib.

androCoder-BD
fonte
0

Swift 5

você precisa usar o método UINib para registrar a célula em 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
fonte
0

No campo “Subclasse de”, selecione UITableViewController.

O título da classe muda para xxxxTableViewController. Deixe como está.

Certifique-se de que a opção “Também criar arquivo XIB” esteja selecionada.

Kai Lean
fonte
0

Eu encontrei esta mensagem quando UITableView no IB foi movido para outra subvisualização com Cmd-C - Cmd-V.

Todos os identificadores, métodos delegados, links no IB etc. permanecem intactos, mas a exceção é levantada no tempo de execução.

A única solução é limpar todas as tintas, relacionadas ao tableview no IB (saída, fonte de dados, delegado) e torná-las novamente.

Vladimir Vodolazkiy
fonte