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?

Jon
quelle

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)
}
Rob Mayoff
quelle
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];    
}
Rohit Mandiwal
quelle
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
        }
    }
Kaz Yoshikawa
quelle
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 
}
Laszlo
quelle
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
    }
}
Stanislav P.
quelle
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
   }
}
Eugene
quelle
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