Usar o método didSelectRowAtIndexPath ou prepareForSegue para UITableView?


101

Estou usando storyboards e tenho um UITableView. Eu tenho uma configuração de segue que empurra da minha mesa para o detalhe VC. Mas qual método devo usar para lidar com isso? Terei que passar alguns objetos para a visualização de detalhes. Mas eu uso didSelectRowAtIndexou -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender?

Respostas:


199

Se você usar prepareForSegue:sender:, não terá muito que mudar se mais tarde decidir acionar a segue de algum controle fora da visualização da tabela.

A prepareForSegue:sender:mensagem é enviada para o controlador de visualização atual, então sugiro algo assim:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // Assume self.view is the table view
    NSIndexPath *path = [self.tableView indexPathForSelectedRow];
    DetailObject *detail = [self detailForIndexPath:path];
    [segue.destinationViewController setDetail:detail];
}

Em Swift:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    let path = self.tableView.indexPathForSelectedRow()!
    segue.destinationViewController.detail = self.detailForIndexPath(path)
}

1
Ok, você pode dar um exemplo de como implementá-lo passando um objeto baseado em indexPath.
Jon

4
não deveria self.viewestar apenas senderaqui? Não consegui nem [self.view indexPathForSelectedRow]trabalhar, tive que fazer[sender indexPathForSelectedRow];
ladookie

Como você faria isso no Swift?
Usuário

@robmayoff Obrigado por atualizar isso para o Swift. Fiz algumas pequenas edições para refletir as alterações recentes de idioma. Espero que isso ajude outras pessoas
Zack Shapiro

É estranho que tableView.indexPathForSelectedRow()contenha o valor correto quando prepareFroSegue...é chamado: só tableView(_:didSelectrowAtIndexPath:)é chamado mais tarde.
Nicolas Miari

5

eu fiz isso e funcionou

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    NSLog(@"Row Selected = %i",indexPath.row);

    [self performSegueWithIdentifier:@"testID" sender:self.view];    
}

11
Isso não faz sentido. Você deve usar a segue OU o delegado de visualização de tabela. Basta criar uma segue a partir da célula e ela executará automaticamente a mesma coisa que você fez sem escrever código.
Yariv Nissim

3
como você atribui uma segue a uma célula sem didSelectRow?
Morkrom de

3

Quando o remetente é UITableViewCell, você pode pedir a UITableView para consultar indexPath da célula.

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if let cell = sender as? UITableViewCell {
            let indexPath = self.tableView.indexPathForCell(cell)!
            assert(segue.destinationViewController.isKindOfClass(DetailViewController))
            let detailViewController = segue.destinationViewController as! DetailViewController
            detailViewController.item = self.items[indexPath.row] // like this
        }
    }

1

se sua propriedade tableView estiver em outra classe e você tiver apenas uma seção , poderá usar a tagpropriedade para armazenar a linha da célula como:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];

     cell.tag = indexPath.row;

     return cell;
}

E então você pode acessá-lo porque senderé a mesma célula com o valor da linha em sua tag:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    MyDestinationViewController *destinationViewController = segue.destinationViewController;
    destinationViewController.myProperty = [tableViewElementsArray objectAtIndex:[sender tag]]; // sender will be your cell 
}

1

self.tableView.indexPathForSelectedRowretorna a célula selecionada, mas não segue a célula do remetente, por exemplo, a célula do remetente não está selecionada (ação acessória) ou em caso de seleção múltipla. A melhor maneira é obter indexPath para o remetente segue:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    __auto_type itemViewController = (id<ItemViewController>)segue.destinationViewController;
    itemViewController.senderIndexPath = [self.tableView indexPathForCell:sender];
}

Em Swift:

protocol ItemViewController {
    var senderIndexPath : IndexPath? { get set }
    var selectedIndexPaths : [IndexPath]? { get set }
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if  let cell = sender as? UITableViewCell,
        var itemViewController = segue.destination as? ItemViewController {
        itemViewController.senderIndexPath = tableView.indexPath(for: cell)
        itemViewController.selectedIndexPaths = tableView.indexPathsForSelectedRows
    }
}

0

Se você usar, prepareForSegue:pode verificar quem é o remetente e executar um código diferente

Por exemplo em rápido

override func prepareForSegue(segue: UiStoryboardSegue, sender: AnyObject?)
{
   var senderIsTableviewCell:Bool! = sender?.isKindOfClass(UITableViewCell)

   if senderIsTableviewCell
   {
       //do something
   }
}

2
Basta fazer: if let tableViewCell = sender as? UITableViewCell {// faça algo} . Se o remetente não puder ser lançado em um UITableViewCell, "faça algo" não será executado.
mbeaty
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.