รับแถวของเซลล์ UITableView เมื่อกดปุ่ม


84

ฉันมีตัวควบคุม tableview ที่แสดงแถวของเซลล์ แต่ละเซลล์มี 3 ปุ่ม ฉันได้กำหนดหมายเลขแท็กสำหรับแต่ละเซลล์เป็น 1,2,3 ปัญหาคือฉันไม่รู้ว่าจะค้นหาเซลล์ที่กดปุ่มได้อย่างไร ขณะนี้ฉันได้รับแท็กของผู้ส่งเมื่อกดปุ่มใดปุ่มหนึ่งเท่านั้น มีวิธีรับหมายเลขแถวเซลล์ด้วยเมื่อกดปุ่มหรือไม่?

คำตอบ:


278

คุณควรใช้วิธีนี้แทน:

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

เวอร์ชัน Swift:

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

ซึ่งจะให้ข้อมูลindexPathตามตำแหน่งของปุ่มที่กด จากนั้นคุณก็โทรหาcellForRowAtIndexPathถ้าคุณต้องการเซลล์หรือindexPath.rowถ้าคุณต้องการหมายเลขแถว

หากคุณหวาดระแวงคุณสามารถตรวจสอบif (indexPath) ...ก่อนใช้งานได้ในกรณีที่indexPathไม่พบจุดนั้นในมุมมองตาราง

คำตอบอื่น ๆ ทั้งหมดมีแนวโน้มที่จะพังหาก Apple ตัดสินใจเปลี่ยนโครงสร้างมุมมอง


8
นี่ล้านครั้ง ไม่มีของคนอื่น ๆ ทำงาน แต่นี่เป็นที่สมบูรณ์แบบและไกลโดยวิธีที่ง่ายที่สุด
INE

2
คำตอบนี้ใช้ได้เพราะเป็นวิธีแก้ปัญหาที่ถูกต้อง อื่น ๆ เป็นวิธีแก้ปัญหา ขอบคุณ!
Bruno Philipe

1
ในกรณีที่คุณไม่ได้มีself.tableviewโปรดดูคำตอบของฉันในหน้านี้
Ashok

1
สิ่งนี้ได้ผลสำหรับฉันเมื่อฉันรู้ว่าผู้ส่งของฉันผิดชั้นเรียน แก้ไขให้เป็น UIButton ที่กดและตอนนี้ใช้งานได้แล้ว!
lordB8r

1
เพียงจำวิธีการที่ไม่ได้convertPoint:*to*View convertPoint:*from*Viewฉันใช้การเติมข้อความอัตโนมัติ Xcode และลงเอยด้วยวิธี fromView เท่านั้นที่ทำให้ไม่ทำงาน ...
tGilani

40

แก้ไข: คำตอบนี้ล้าสมัย โปรดใช้วิธีนี้แทน


ลองสิ่งนี้:

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

แก้ไข: หากคุณใช้ contentView ให้ใช้สิ่งนี้สำหรับ buttonCell แทน:

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

1
คุณไม่ควรเพิ่มมุมมองย่อยลงในเซลล์ แต่เฉพาะในcontentViewคุณสมบัติของเซลล์ดังนั้นวิธีนี้จึงไม่ได้ผลจริงๆ

1
ฉันเห็นด้วยกับ @ H2CO3 และฉันก็ไม่คิดว่าสิ่งนี้ควรทำได้โดยการอ้างอิงซูเปอร์วิว โปรดดูวิธีที่ดีกว่าด้านล่าง: stackoverflow.com/a/16270198/308315
iwasrobbed

@minimalpop ได้โปรดเปลี่ยนคำตอบที่ถูกต้องได้ไหม เพื่อให้มี Q / A ที่ดีขึ้น!
Thomas Besnehard

สิ่งนี้ใช้ไม่ได้ใน iOS 7 ใช้ indexPathForRowAtPoint: คำตอบด้านล่าง
Austin

ฉันลองรุ่นเดียวกันกับ UICollectionView และทำงานได้อย่างสมบูรณ์แบบ ขอบคุณมาก!
Claus

18

ฉันอยากจะแนะนำวิธีนี้ในการดึง indexPath ของเซลล์ที่มีมุมมองย่อยที่กำหนดเอง - ( เข้ากันได้กับ iOS 7 และเวอร์ชันก่อนหน้าทั้งหมด )

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

สิ่งนี้ไม่ต้องการself.tablviewอย่างใดอย่างหนึ่ง

นอกจากนี้โปรดสังเกตรหัสที่แสดงความคิดเห็นซึ่งมีประโยชน์หากคุณต้องการเช่นเดียวกันผ่านทาง @selector ของ UIGestureRecognizer ที่เพิ่มลงในมุมมองย่อยที่กำหนดเองของคุณ


จะเกิดอะไรขึ้นถ้าฉันต้องการข้อมูลที่พบใน uitableviewcontroller?
iosMentalist

คำตอบที่ดีหากคุณมีแถบค้นหาและต้องการทราบว่าตารางใดที่ใช้ในขณะนี้คุณสามารถใช้สิ่งนี้ได้ด้วย
Suraj K Thomas

ลำดับชั้นของเซลล์ตารางเปลี่ยนไปหรือไม่ คุณช่วยให้ฉันเข้าใจว่ามีการเปลี่ยนแปลงอะไรเกิดขึ้นและสามารถเปลี่ยนแปลงต่อไปได้หรือไม่
Kamaldeep singh Bhatia

3

มีสองวิธี:

  1. @ H2CO3 อยู่พอดี คุณสามารถทำตามที่ @ user523234 แนะนำ แต่มีการเปลี่ยนแปลงเล็กน้อยเพื่อเคารพ UITableViewCellContentView ที่ควรอยู่ระหว่าง UIButton และ UITableViewCell ดังนั้นเพื่อแก้ไขรหัสของเขา:

    - (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. หากคุณสร้าง UITableViewCell ที่กำหนดเอง (คลาสย่อยของคุณเอง) คุณสามารถเรียกselfใช้ IBAction ได้ คุณสามารถเชื่อมโยงฟังก์ชัน IBAction กับปุ่มของคุณได้โดยใช้สตอรีบอร์ดหรือทางโปรแกรมเมื่อคุณตั้งค่าเซลล์

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

2

ฉันถือว่าคุณเพิ่มปุ่มลงในเซลล์cellForRowAtIndexPathแล้วสิ่งที่ฉันจะทำคือสร้างคลาสย่อยของคลาสที่กำหนดเองUIButtonเพิ่มแท็กที่เรียกว่าrowNumberและต่อท้ายข้อมูลนั้นในขณะที่คุณเพิ่มปุ่มลงในเซลล์


3
ไม่เป็นไร แต่ไม่มีเหตุผลที่จะสร้างคลาสย่อยUIButtonสำหรับมัน เป็นสถานที่ให้บริการร่วมกันของtag UIView
Rob Napier

ไม่รู้ว่าฉันกำลังคิดอะไรอยู่และถือว่าUIบางอย่างไม่ใช่UIขอบคุณสำหรับการแก้ไข!
Derek Li

2

อีกวิธีง่ายๆ:

  • รับจุดสัมผัสใน tableView

  • จากนั้นรับเส้นทางดัชนีของเซลล์ที่จุด

  • เส้นทางดัชนีประกอบด้วยดัชนีแถว

รหัสคือ:

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

สวิฟต์ 3

หมายเหตุ: สิ่งนี้ควรอยู่ในคำตอบที่ยอมรับข้างต้นยกเว้นว่าเมตาขมวดคิ้วเมื่อแก้ไขดังกล่าว

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

สองความคิดเห็นเล็กน้อย:

  1. ฟังก์ชันเริ่มต้นมีประเภทผู้ส่งเป็น Any ซึ่งไม่มีการแปลง
  2. CGPointZero สามารถถูกแทนที่ด้วย CGPoint ()

ทำงานได้อย่างสมบูรณ์

0

วิธีแก้ปัญหาหนึ่งคือตรวจสอบแท็กของ superview ของปุ่มหรือสูงกว่าในลำดับชั้นมุมมอง (หากปุ่มอยู่ในมุมมองเนื้อหาของเซลล์)


0

ฉันต้องการแบ่งปันรหัสอย่างรวดเร็ว -

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

อย่างรวดเร็ว:

@IBAction func buttonAction(_ sender: UIButton) {
    guard let indexPath = tableView.indexPathForRow(at: sender.convert(CGPoint(), to: tableView)) else {
        return
    }
    // do something
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.