Gunakan didSelectRowAtIndexPath atau metode preparedForSegue untuk UITableView?

101

Saya menggunakan storyboard dan saya memiliki UITableView. Saya memiliki pengaturan segue yang mendorong dari tabel saya ke detail VC. Tetapi metode mana yang harus saya gunakan untuk menangani ini? Saya harus memberikan beberapa objek ke tampilan detail. Tapi apakah saya menggunakan didSelectRowAtIndexatau -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender?

Jon
sumber

Jawaban:

199

Jika Anda menggunakan prepareForSegue:sender: maka Anda tidak akan memiliki banyak perubahan jika Anda kemudian memutuskan untuk memicu segue dari beberapa kontrol di luar tampilan tabel.

The prepareForSegue:sender:pesan dikirim ke controller tampilan saat ini, jadi saya akan menyarankan sesuatu seperti ini:

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

Di Swift:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    let path = self.tableView.indexPathForSelectedRow()!
    segue.destinationViewController.detail = self.detailForIndexPath(path)
}
merampok mayoff
sumber
1
Oke, dapatkah Anda memberikan contoh cara mengimplementasikannya dengan meneruskan objek berdasarkan indexPath.
Jon
4
seharusnya tidak self.viewhanya berada di sendersini? Saya bahkan tidak bisa [self.view indexPathForSelectedRow]bekerja, saya harus melakukannya[sender indexPathForSelectedRow];
ladookie
Bagaimana Anda melakukan ini di Swift?
Pengguna
@robmayoff Terima kasih telah memperbarui ini untuk Swift. Saya membuat sedikit pengeditan untuk mencerminkan perubahan bahasa terkini. Semoga ini bisa membantu orang lain
Zack Shapiro
Aneh sekali yang tableView.indexPathForSelectedRow()berisi nilai yang benar ketika prepareFroSegue...dipanggil: tableView(_:didSelectrowAtIndexPath:)tidak dipanggil sampai nanti.
Nicolas Miari
5

Saya melakukan ini dan berhasil

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

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

    [self performSegueWithIdentifier:@"testID" sender:self.view];    
}
Rohit Mandiwal
sumber
11
Itu tidak masuk akal. Anda harus menggunakan segue ATAU delegasi tampilan tabel. Buat saja segue dari Sel dan secara otomatis akan melakukan hal yang sama yang Anda lakukan tanpa menulis kode.
Yariv Nissim
3
bagaimana Anda menetapkan segue ke sel tanpa didSelectRow?
Mork mulai
3

Jika pengirimnya adalah UITableViewCell, Anda dapat meminta UITableView untuk melakukan kueri indexPath sel.

    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
sumber
1

jika properti tableView Anda berada di kelas lain dan Anda hanya memiliki satu bagian , Anda dapat menggunakan tagproperti untuk menyimpan baris sel seperti:

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

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

     cell.tag = indexPath.row;

     return cell;
}

Dan kemudian Anda dapat mengaksesnya karena sendersel yang sama dengan nilai baris di tag-nya:

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

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

self.tableView.indexPathForSelectedRowmengembalikan sel yang dipilih, tetapi tidak memisahkan sel pengirim, misalnya sel pengirim tidak dipilih (tindakan aksesori), atau dalam kasus pemilihan ganda. Cara terbaik adalah mendapatkan indexPath untuk pengirim segue:

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

Di 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.
sumber
0

Jika Anda menggunakan prepareForSegue:Anda dapat memeriksa siapa pengirimnya dan menjalankan kode yang berbeda

Misalnya dengan sigap

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

   if senderIsTableviewCell
   {
       //do something
   }
}
Eugene
sumber
2
Lakukan saja: jika biarkan tableViewCell = sender as? UITableViewCell {// lakukan sesuatu} . Jika pengirim tidak dapat dikirim ke UITableViewCell, "lakukan sesuatu" tidak akan dijalankan.
mbeaty