Bắt hàng ô UITableView khi nhấn nút


84

Tôi có bộ điều khiển chế độ xem bảng hiển thị một hàng ô. Mỗi ô có 3 nút. Tôi đã đánh số các thẻ cho mỗi ô là 1,2,3. Vấn đề là tôi không biết làm thế nào để tìm thấy một nút đang được nhấn trên ô nào. Tôi hiện chỉ nhận được thẻ của người gửi khi một trong các nút đã được nhấn. Có cách nào để lấy số hàng ô cũng như khi nhấn nút không?

Câu trả lời:


278

Bạn thực sự nên sử dụng phương pháp này thay thế:

CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];

Phiên bản Swift:

let buttonPosition = sender.convert(CGPoint(), to:tableView)
let indexPath = tableView.indexPathForRow(at:buttonPosition)

Điều đó sẽ cung cấp cho bạn indexPathdựa trên vị trí của nút đã được nhấn. Sau đó, bạn chỉ cần gọi cellForRowAtIndexPathnếu bạn cần ô hoặc indexPath.rownếu bạn cần số hàng.

Nếu hoang tưởng, bạn có thể kiểm tra if (indexPath) ...trước khi sử dụng nó đề phòng trường hợp indexPathkhông tìm thấy điểm đó trên chế độ xem bảng.

Tất cả các câu trả lời khác có khả năng bị phá vỡ nếu Apple quyết định thay đổi cấu trúc chế độ xem.


8
điều này, một triệu lần. none của những người khác làm việc, nhưng điều này là hoàn hảo và đến nay là giải pháp đơn giản nhất
ine

2
Câu trả lời này hoạt động vì nó là giải pháp chính xác . Những người khác là giải pháp thay thế. Cảm ơn!
Bruno Philipe

1
Trong trường hợp bạn khôngself.tableview , vui lòng tham khảo câu trả lời của tôi trên trang này.
Ashok

1
Điều này có hiệu quả với tôi khi tôi nhận ra người gửi của mình không đúng lớp. Đã sửa nó thành UIButton được nhấn và bây giờ nó đang hoạt động!
LordB8r

1
chỉ cần nhớ phương pháp là convertPoint:*to*Viewkhông convertPoint:*from*View. Tôi sử dụng Xcode autocomplete và kết thúc với phương pháp fromView chỉ dẫn đến không làm việc ...
tGilani

40

Chỉnh sửa: Câu trả lời này đã lỗi thời. Vui lòng sử dụng phương pháp này thay thế


Thử đi:

-(void)button1Tapped:(id)sender
{
    UIButton *senderButton = (UIButton *)sender;
    UITableViewCell *buttonCell = (UITableViewCell *)[senderButton superview];
    UITableView* table = (UITableView *)[buttonCell superview];
    NSIndexPath* pathOfTheCell = [table indexPathForCell:buttonCell];
    NSInteger rowOfTheCell = [pathOfTheCell row];
    NSLog(@"rowofthecell %d", rowOfTheCell);
}

Chỉnh sửa: Nếu bạn đang sử dụng contentView, hãy sử dụng cái này cho buttonCell thay thế:

UITableViewCell *buttonCell = (UITableViewCell *)senderButton.superview.superview;

1
Bạn không được thêm các lượt xem phụ vào chính ô mà chỉ vào thuộc tính của nó contentView- vì vậy giải pháp này không thực sự hoạt động.

1
Tôi đồng ý với @ H2CO3 và tôi cũng không nghĩ rằng điều này nên được thực hiện bằng cách tham khảo superviews. Vui lòng xem cách tốt hơn bên dưới: stackoverflow.com/a/16270198/308315
iwasrobbed

@minimalpop bạn có thể thay đổi câu trả lời đúng được không? để có Q / A tốt hơn!
Thomas Besnehard

Điều này không hoạt động trong iOS 7. Sử dụng indexPathForRowAtPoint: câu trả lời bên dưới
Austin

Tôi đã thử phiên bản tương tự với UICollectionView và hoạt động hoàn hảo. Cảm ơn rất nhiều!
Claus

18

Tôi muốn giới thiệu cách này để tìm nạp indexPath của ô có bất kỳ chế độ xem phụ tùy chỉnh nào - ( tương thích với iOS 7 cũng như tất cả các phiên bản trước )

-(void)button1Tapped:(id)sender {
//- (void)cellSubviewTapped:(UIGestureRecognizer *)gestureRecognizer {
//    UIView *parentCell = gestureRecognizer.view.superview;
    UIView *parentCell = sender.superview;

    while (![parentCell isKindOfClass:[UITableViewCell class]]) {   // iOS 7 onwards the table cell hierachy has changed.
        parentCell = parentCell.superview;
    }

    UIView *parentView = parentCell.superview;

    while (![parentView isKindOfClass:[UITableView class]]) {   // iOS 7 onwards the table cell hierachy has changed.
        parentView = parentView.superview;
    }


    UITableView *tableView = (UITableView *)parentView;
    NSIndexPath *indexPath = [tableView indexPathForCell:(UITableViewCell *)parentCell];

    NSLog(@"indexPath = %@", indexPath);
}

Điều này cũng không yêu cầu self.tablview.

Ngoài ra, hãy lưu ý mã được nhận xét hữu ích nếu bạn muốn giống như vậy thông qua @selector của UIGestureRecognizer được thêm vào chế độ xem phụ tùy chỉnh của bạn.


Còn nếu tôi cần dữ liệu được tìm thấy trong uitableviewcontroller thì sao?
iosMentalist

Câu trả lời hay. Nếu bạn có thanh tìm kiếm và muốn biết bảng nào được sử dụng vào lúc này, bạn cũng có thể sử dụng bảng này.
Suraj K Thomas

phân cấp ô trong bảng đã thay đổi? bạn có thể giúp tôi hiểu rằng những thay đổi nào đã xảy ra và nó có thể thay đổi thêm không?
Kamaldeep singh Bhatia

3

Có hai cách:

  1. @ H2CO3 đều đúng. Bạn có thể thực hiện những gì @ user523234 đã đề xuất, nhưng với một thay đổi nhỏ, để tôn trọng UITableViewCellContentView sẽ nằm giữa UIButton và UITableViewCell. Vì vậy, để sửa đổi mã của anh ấy:

    - (IBAction)button1Tapped:(id)sender
    {
        UIButton *senderButton = (UIButton *)sender;
        UITableViewCellContentView *cellContentView = (UITableViewCellContentView *)senderButton.superview;
        UITableViewCell *tableViewCell = (UITableViewCell *)cellContentView.superview;
        UITableView* tableView = (UITableView *)tableViewCell.superview;
        NSIndexPath* pathOfTheCell = [tableView indexPathForCell:tableViewCell];
        NSInteger rowOfTheCell = pathOfTheCell.row;
        NSLog(@"rowofthecell %d", rowOfTheCell);
    }
    
  2. Nếu bạn tạo một UITableViewCell tùy chỉnh (lớp con của riêng bạn), thì bạn có thể chỉ cần gọi selftrong IBAction. Bạn có thể liên kết chức năng IBAction với nút của mình bằng cách sử dụng bảng phân cảnh hoặc theo chương trình khi bạn thiết lập ô.

    - (IBAction)button1Tapped:(id)sender
    {
        UITableView* tableView = (UITableView *)self.superview;
        NSIndexPath* pathOfTheCell = [tableView indexPathForCell:self];
        NSInteger rowOfTheCell = pathOfTheCell.row;
        NSLog(@"rowofthecell %d", rowOfTheCell);
    }
    

2

Tôi giả sử bạn thêm các nút vào ô cellForRowAtIndexPath, sau đó những gì tôi sẽ làm là tạo một lớp con của lớp tùy chỉnh UIButton, thêm một thẻ được gọi rowNumbervà nối dữ liệu đó trong khi bạn thêm nút vào ô.


3
Điều này là tốt, nhưng không có lý do gì để tạo một lớp con của UIButtonnó. taglà tài sản chung của UIView.
Rob Napier

Không biết tôi đang nghĩ gì và cho rằng UI gì đó không phải là UI , cảm ơn bạn đã sửa!
Derek Li

2

Một cách đơn giản khác:

  • Nhận điểm liên lạc trong tableView

  • Sau đó, lấy đường dẫn chỉ mục của ô tại điểm

  • Đường dẫn chỉ mục chứa chỉ mục hàng

Mã là:

- (void)buttonTapped:(id)sender {
    UITapGestureRecognizer *tap = (UITapGestureRecognizer *)sender;
    CGPoint point = [tap locationInView:theTableView];

    NSIndexPath *theIndexPath = [theTableView indexPathForRowAtPoint:point];

    NSInteger theRowIndex = theIndexPath.row;
    // do your stuff here
    // ...
}

1

Swift 3

Lưu ý: Điều này thực sự nên đi trong câu trả lời được chấp nhận ở trên, ngoại trừ việc meta cau mày khi chỉnh sửa như vậy.

@IBAction func doSomething(_ sender: UIButton) {
   let buttonPosition = sender.convert(CGPoint(), to: tableView)
   let index = tableView.indexPathForRow(at: buttonPosition)
}

Hai nhận xét nhỏ:

  1. Hàm mặc định có loại người gửi là Bất kỳ, không có chuyển đổi.
  2. CGPointZero có thể được thay thế bằng CGPoint ()

Hoạt động hoàn hảo.

0

Một giải pháp có thể là kiểm tra thẻ của chế độ xem siêu cao của nút hoặc thậm chí cao hơn trong phân cấp chế độ xem (nếu nút nằm trong chế độ xem nội dung của ô).


0

Tôi muốn chia sẻ mã nhanh chóng -

extension UITableView
{
    func indexPathForCellContainingView(view1:UIView?)->NSIndexPath?
    {
        var view = view1;
        while view != nil {
            if (view?.isKindOfClass(UITableViewCell) == true)
            {
                return self.indexPathForCell(view as! UITableViewCell)!
            }
            else
            {
                view = view?.superview;
            }
        }
        return nil
    }
}

0

Nhanh chóng:

@IBAction func buttonAction(_ sender: UIButton) {
    guard let indexPath = tableView.indexPathForRow(at: sender.convert(CGPoint(), to: tableView)) else {
        return
    }
    // do something
}
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.