Utilizzare didSelectRowAtIndexPath o il metodo prepareForSegue per UITableView?


101

Sto usando gli storyboard e ho un UITableView. Ho una configurazione Segue che spinge dal mio tavolo al dettaglio VC. Ma quale metodo dovrei usare per gestirlo? Dovrò passare un paio di oggetti alla visualizzazione dei dettagli. Ma io uso didSelectRowAtIndexo -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender?

Risposte:


199

Se lo usi prepareForSegue:sender:, non avrai molto da cambiare se in seguito decidi di attivare il segue da qualche controllo al di fuori della visualizzazione tabella.

Il prepareForSegue:sender:messaggio viene inviato al controller di visualizzazione corrente, quindi suggerirei qualcosa del genere:

- (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];
}

In Swift:

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

1
Ok, puoi fare un esempio di come implementarlo passando un oggetto basato su indexPath.
Jon

4
non dovrebbe self.viewessere solo senderqui? Non potevo nemmeno andare [self.view indexPathForSelectedRow]al lavoro, dovevo farlo[sender indexPathForSelectedRow];
ladookie

Come lo faresti in Swift?
Utente

@robmayoff Grazie per aver aggiornato questo per Swift. Ho apportato alcune lievi modifiche per riflettere i recenti cambiamenti nella lingua. Spero che questo aiuti alcuni altri
Zack Shapiro

È strano che tableView.indexPathForSelectedRow()contenga il valore corretto quando prepareFroSegue...viene chiamato: tableView(_:didSelectrowAtIndexPath:)non viene chiamato fino a dopo.
Nicolas Miari

5

L'ho fatto e ha funzionato

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

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

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

11
Non ha senso. È necessario utilizzare il segue OPPURE il delegato della vista tabella. Basta creare un segue dalla cella e eseguirà automaticamente la stessa cosa che hai fatto senza scrivere codice.
Yariv Nissim

3
come si assegna un segue a una cella senza didSelectRow?
Mork dal

3

Quando il mittente è UITableViewCell, puoi chiedere a UITableView di interrogare indexPath della cella.

    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 la tua proprietà tableView è in un'altra classe e hai solo una sezione , puoi usare la tagproprietà per memorizzare la riga della cella come:

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

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

     cell.tag = indexPath.row;

     return cell;
}

E poi puoi accedervi poiché senderè la stessa cella con il valore della riga nel suo 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.indexPathForSelectedRowrestituisce la cella selezionata, ma non segue la cella del mittente, ad esempio la cella del mittente non è selezionata (azione accessoria) o in caso di selezione multipla. Il modo migliore è ottenere indexPath per segue mittente:

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

In 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 usi prepareForSegue:puoi controllare chi è il mittente ed eseguire codice diverso

Ad esempio in swift

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

   if senderIsTableviewCell
   {
       //do something
   }
}

2
Basta fare: if let tableViewCell = sender as? UITableViewCell {// fai qualcosa} . Se il mittente non può essere trasmesso a un UITableViewCell, "fai qualcosa" non verrà eseguito.
mbeaty
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.