Sử dụng phương thức didSelectRowAtIndexPath hoặc phương thức readyForSegue cho UITableView?


101

Tôi đang sử dụng bảng phân cảnh và tôi có UITableView. Tôi có một thiết lập segue đẩy từ bảng của tôi đến VC chi tiết. Nhưng tôi nên sử dụng phương pháp nào để xử lý điều này? Tôi sẽ phải chuyển một vài đối tượng vào chế độ xem chi tiết. Nhưng tôi có sử dụng didSelectRowAtIndexhay -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)senderkhông?

Câu trả lời:


199

Nếu bạn sử dụng prepareForSegue:sender:thì bạn sẽ không có nhiều thứ để thay đổi nếu sau này bạn quyết định kích hoạt segue từ một số điều khiển bên ngoài chế độ xem bảng.

Các prepareForSegue:sender:tin nhắn sẽ được gửi đến bộ điều khiển xem hiện tại, vì vậy tôi muốn đề nghị một cái gì đó như thế này:

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

Trong Swift:

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

1
Được rồi, bạn có thể cho một ví dụ về cách triển khai nó với việc truyền một đối tượng dựa trên indexPath.
Jon

4
không self.viewnên chỉ senderở đây? Tôi thậm chí không thể có được [self.view indexPathForSelectedRow]để làm việc, tôi phải làm[sender indexPathForSelectedRow];
ladookie

Bạn sẽ làm điều này như thế nào trong Swift?
Người dùng

@robmayoff Cảm ơn bạn đã cập nhật điều này cho Swift. Tôi đã thực hiện một số chỉnh sửa nhỏ để phản ánh những thay đổi ngôn ngữ gần đây. Hy vọng điều này sẽ giúp một số người khác
Zack Shapiro

Thật kỳ lạ khi tableView.indexPathForSelectedRow()chứa giá trị chính xác khi prepareFroSegue...được gọi: tableView(_:didSelectrowAtIndexPath:)không được gọi cho đến sau này.
Nicolas Miari

5

Tôi đã làm điều này và nó hoạt động

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

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

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

11
Điều đó không có ý nghĩa. Bạn nên sử dụng segue HOẶC đại biểu chế độ xem bảng. Chỉ cần tạo một segue từ Cell và nó sẽ tự động thực hiện điều tương tự như bạn đã làm mà không cần viết mã.
Yariv Nissim

3
làm thế nào để bạn gán một segue cho một ô mà không có didSelectRow?
Morkrom

3

Khi người gửi là UITableViewCell, bạn có thể yêu cầu UITableView truy vấn indexPath của ô.

    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

nếu thuộc tính tableView của bạn thuộc một lớp khác và bạn chỉ có một phần , thì bạn có thể sử dụng thuộc tagtính để lưu trữ hàng của ô như:

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

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

     cell.tag = indexPath.row;

     return cell;
}

Và sau đó, bạn có thể truy cập nó vì sendercùng một ô với giá trị hàng trong thẻ của nó:

- (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.indexPathForSelectedRowtrả về ô đã chọn, nhưng không trả về ô người gửi, ví dụ: ô người gửi không được chọn (hành động phụ) hoặc trong nhiều trường hợp lựa chọn. Cách tốt nhất là lấy indexPath cho người gửi segue:

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

Trong 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

Nếu sử dụng, prepareForSegue:bạn có thể kiểm tra xem ai là người gửi và thực thi mã khác

Ví dụ trong nhanh chóng

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

   if senderIsTableviewCell
   {
       //do something
   }
}

2
Chỉ cần làm: if let tableViewCell = sender as? UITableViewCell {// làm gì đó} . Nếu người gửi không thể được truyền đến UITableViewCell, "làm gì đó" sẽ không thực thi.
mbeaty
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.