Verwenden Sie die Methode didSelectRowAtIndexPath oder prepareForSegue für UITableView?


101

Ich verwende Storyboards und habe eine UITableView. Ich habe ein Segue-Setup, das von meinem Tisch zum Detail VC wechselt. Aber mit welcher Methode soll ich damit umgehen? Ich muss ein paar Objekte an die Detailansicht übergeben. Aber benutze ich didSelectRowAtIndexoder -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender?

Antworten:


199

Wenn Sie verwenden, müssen prepareForSegue:sender:Sie nicht so viel ändern, wenn Sie später entscheiden, den Übergang von einem Steuerelement außerhalb der Tabellenansicht aus auszulösen.

Die prepareForSegue:sender:Nachricht wird an den aktuellen Ansichts-Controller gesendet, daher würde ich Folgendes vorschlagen:

- (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, können Sie ein Beispiel geben, wie Sie es implementieren, indem Sie ein auf indexPath basierendes Objekt übergeben.
Jon

4
sollte nicht self.vieweinfach senderhier sein? Ich konnte nicht einmal [self.view indexPathForSelectedRow]zur Arbeit, ich musste tun[sender indexPathForSelectedRow];
Ladookie

Wie würden Sie das in Swift machen?
Benutzer

@robmayoff Danke, dass du dies für Swift aktualisiert hast. Ich habe einige geringfügige Änderungen vorgenommen, um die jüngsten Sprachänderungen widerzuspiegeln. Hoffe das hilft einigen anderen
Zack Shapiro

Es ist seltsam, dass beim tableView.indexPathForSelectedRow()Aufrufen der richtige Wert enthalten prepareFroSegue...ist: tableView(_:didSelectrowAtIndexPath:)Wird erst später aufgerufen.
Nicolas Miari

5

Ich habe das gemacht und es hat funktioniert

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

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

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

11
Das macht keinen Sinn. Sie sollten entweder den Segue ODER den Delegierten der Tabellenansicht verwenden. Erstellen Sie einfach einen Übergang aus der Zelle und es wird automatisch das gleiche ausgeführt, was Sie getan haben, ohne Code zu schreiben.
Yariv Nissim

3
Wie ordnet man einer Zelle ohne didSelectRow einen Segue zu?
Morkrom

3

Wenn der Absender UITableViewCell ist, können Sie UITableView auffordern, den Indexpfad der Zelle abzufragen.

    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

Wenn sich Ihre tableView-Eigenschaft in einer anderen Klasse befindet und Sie nur einen Abschnitt haben , können Sie die tagEigenschaft verwenden, um die Zeile der Zelle wie folgt zu speichern:

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

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

     cell.tag = indexPath.row;

     return cell;
}

Und dann können Sie darauf zugreifen, da senderes sich um dieselbe Zelle mit dem Zeilenwert in ihrem Tag handelt:

- (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.indexPathForSelectedRowGibt die ausgewählte Zelle zurück, aber nicht die Absenderzelle, z. B. ist die Absenderzelle nicht ausgewählt (Zusatzaktion) oder in einem Fall mit Mehrfachauswahl. Der beste Weg ist, indexPath für den Absender zu erhalten:

- (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

Wenn Sie verwenden prepareForSegue:, können Sie überprüfen, wer der Absender ist, und anderen Code ausführen

Zum Beispiel in schnell

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

   if senderIsTableviewCell
   {
       //do something
   }
}

2
Tun Sie einfach: Wenn tableViewCell = Absender als? UITableViewCell {// etwas tun} . Wenn der Absender nicht in eine UITableViewCell umgewandelt werden kann, wird "etwas tun" nicht ausgeführt.
mbeaty
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.