Referência de UITableViewCell para o pai UITableView?

Existe alguma maneira de acessar o UITableView de dentro de um UITableViewCell ?

Armazene uma referência weak ao tableView na célula, que você configuraria em -tableView:cellForRowAtIndexPath: do dataSource de sua tabela.

Isso é melhor do que confiar em self.superview para sempre ser exatamente o tableView é frágil. Quem sabe como a Apple pode reorganizar a hierarquia de visualizações do UITableView no futuro.

Aqui está uma maneira mais agradável de fazer isso, que não depende de nenhuma hierarquia específica do UITableView. Ele funcionará com qualquer futura versão do iOS, desde que o UITableView não altere completamente o nome da class. Não só isso é extremamente improvável, mas se isso acontecer, você terá que retocar seu código de qualquer maneira.

Basta importar a categoria abaixo e obter sua referência com [myCell parentTableView]

 @implementation UIView (FindUITableView) -(UITableView *) parentTableView { // iterate up the view hierarchy to find the table containing this cell/view UIView *aView = self.superview; while(aView != nil) { if([aView isKindOfClass:[UITableView class]]) { return (UITableView *)aView; } aView = aView.superview; } return nil; // this view is not within a tableView } @end 

 // To use it, just import the category and invoke it like so: UITableView *myTable = [myTableCell parentTableView]; // It can also be used from any subview within a cell, from example // if you have a UILabel within your cell, you can also do: UITableView *myTable = [myCellLabel parentTableView]; // NOTE: // If you invoke this on a cell that is not part of a UITableView yet // (ie, on a cell that you just created with [[MyCell alloc] init]), // then you will obviously get nil in return. You need to invoke this on cells/subviews // that are already part of a UITableView. 

ATUALIZAR
Há alguma discussão nos comentários sobre se manter uma referência fraca é uma abordagem melhor. Depende das suas circunstâncias. Atravessar a hierarquia de exibição tem uma pequena penalidade de tempo de execução quando você está em loop até que o UIView de destino seja identificado. Quão profundas são suas opiniões? Por outro lado, manter uma referência em cada célula tem uma penalidade de memory mínima (uma referência fraca é um ponteiro, afinal) e, geralmente, adicionar relacionamentos de objects onde eles não são necessários é considerado uma prática ruim de design OO por várias razões. ser evitado (veja detalhes nos comentários abaixo).

Mais importante ainda, manter referências de tabela dentro de células adiciona complexidade de código e pode levar a erros, porque UITableViewCells são reutilizáveis. Não é coincidência que o UIKit não inclua uma propriedade cell.parentTable . Se você definir o seu próprio, você deve adicionar código para gerenciá-lo, e se você falhar em fazê-lo efetivamente, você poderá introduzir vazamentos de memory (isto é, as células vivem após o tempo de vida de sua tabela).

Como normalmente você estará usando a categoria acima quando um usuário interage com uma célula (execute para uma única célula), e não quando organiza a tabela em [tableView:cellForRowAtIndexPath:] (execute para todas as células visíveis), o runtime custo deve ser insignificante.

Xcode 7 beta, Swift 2.0

Isso funciona bem para mim, na minha opinião, não tem nada a ver com a hierarquia ou qualquer outra coisa. Eu não tive problemas com essa abordagem até agora. Eu usei isso para muitos callbacks asynchronouss (por exemplo, quando uma solicitação da API é feita).

Classe TableViewCell

 class ItemCell: UITableViewCell { var updateCallback : ((updateList: Bool)-> Void)? //add this extra var @IBAction func btnDelete_Click(sender: AnyObject) { let localStorage = LocalStorage() if let description = lblItemDescription.text { //I delete it here, but could be done at other class as well. localStorage.DeleteItem(description) } updateCallback?(updateList : true) } } 

Classe de exibição de tabela interna que implementa o DataSource e Delegate

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell: ItemCell = self.ItemTableView.dequeueReusableCellWithIdentifier("ItemCell") as! ItemCell! cell.updateCallback = UpdateCallback //add this extra line cell.lblItemDescription?.text = self.SomeList[indexPath.row].Description return cell } func UpdateCallback(updateTable : Bool) //add this extra method { licensePlatesList = localStorage.LoadNotificationPlates() LicenseTableView.reloadData() } 

Claro que você pode colocar qualquer variável no updateCallback e alterar sua function no tableView acordo.

Alguém pode querer me dizer se é melhor usá-lo, só para ter certeza.

Você precisa adicionar uma referência ao UITableView ao construir a célula de exibição de tabela.

No entanto, quase certamente o que você realmente quer é uma referência ao seu UITableViewController … que requer a mesma coisa, configure-o como um delegado da célula quando você constrói a célula e a entrega à visão de tabela.

Uma abordagem alternativa se você estiver conectando ações é construir as células no IB, com o controlador de exibição de tabela como o proprietário dos arquivos – depois, conecte os botões na célula às ações no controlador de exibição de tabela. Quando você carregar o xib da célula com loadNibNamed, passe o controlador de visualização como o proprietário e as ações do botão serão ligadas de volta ao controlador de exibição de tabela.

Se você tiver classs personalizadas para seu UITableViewCells, você pode adicionar uma variável de tipo de identificação no header da célula e sintetizar a variável. Depois de definir a variável quando você carrega a célula, você está livre para fazer o que quiser com a tableview ou qualquer outra visualização superior sem muita complicação ou sobrecarga.

cell.h

  // interface id root; // propery @property (nonatomic, retain) id root; 

cell.m

@sintetiza a raiz;

tableviewcontroller.m

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // blah blah, traditional cell declaration // but before return cell; cell.root = tableView; } 

Agora você pode chamar qualquer um dos methods da tableview de dentro de sua célula usando a variável raiz. (por exemplo, [root reloadData]);

Ah, me leva de volta aos bons e velhos tempos da programação em flash.

Os dois methods em outras respostas são: (A) armazenar uma referência à tabela, ou (B) subir as super visões.

Eu sempre usaria algo como (A) para objects de modelo e (B) para células de tabela.

Células

Se você está lidando com um UITableViewCell, então AFAIK você deve ter o UITableView na mão (digamos que você está em um método delegado de tabela), ou está lidando com uma célula visível que está na hierarquia da visão. Caso contrário, você pode estar fazendo algo errado (por favor, note o “pode ​​bem”).

As células são liberadas reutilmente e se acontecer de você ter uma que não é visível, a única razão real que a célula existe é a otimização de desempenho do iOS UITableView (uma versão mais lenta do iOS teria liberado e esperançosamente desalocou a célula quando ela saiu da canvas ) ou porque você tem uma referência específica a ele. Eu acho que esta é provavelmente a razão pela qual as células da tabela não são dotadas de um método de instância tableView.

Então, (B) dá o resultado certo para todos os iOS’s até agora, e todos os futuros, até que eles mudem radicalmente como as visualizações funcionam.

Embora, a fim de evitar escrever código generalizável várias vezes, eu usaria isso:

 +(id)enclosingViewOfView:(UIView*)view withClass:(Class)returnKindOfClass { while (view&&![view isKindOfClass:returnKindOfClass]) view=view.superview; return(view); } 

e um método de conveniência:

 +(UITableView*)tableForCell:(UITableViewCell*)cell { return([self enclosingViewOfView:cell.superview withClass:UITableView.class]); } 

(ou categorias, se você gosta)

BTW, se você está preocupado com o efeito de um loop com 20 ou mais iterações desse tamanho no desempenho do aplicativo, não.

Modelos

Se você está falando sobre o object modelo que é exibido na célula, então definitivamente esse modelo poderia / deveria saber sobre seu modelo pai, que pode ser usado para localizar ou desencadear mudanças na (s) tabela (s) que o modelo da célula pode Isso é como (A), mas menos frágil com futuras atualizações do iOS (por exemplo, um dia eles podem fazer o cache de reutilização do UITableViewCell existir por reuseidentifier, em vez de por reuseidentifier por tableview, nesse dia todas as implementações que usam o fraco método de referência irá quebrar).

O método modelo seria usado para alterações nos dados exibidos na célula (ou seja, mudanças no modelo), já que as alterações se propagam onde quer que o modelo seja exibido (por exemplo, algum outro UIViewController em outro lugar no aplicativo, registro, …)

O método cell seria usado para ações tableview, o que provavelmente seria uma má ideia se a célula não fosse sequer uma subvisualização de uma tabela (embora seja o seu código, enlouqueça).

De qualquer forma, use um teste de unidade em vez de assumir que o código aparentemente mais limpo só funciona quando atualiza o iOS.

 UITableView *tv = (UITableView *) self.superview.superview; UITableViewController *vc = (UITableViewController *) tv.dataSource;