Düğmeye basıldığında UITableView hücresinin satırını alma


84

Bir hücre satırını görüntüleyen bir tablo görünümü denetleyicim var. Her hücrenin 3 düğmesi vardır. Her hücrenin etiketlerini 1,2,3 olacak şekilde numaralandırdım. Sorun şu ki, hangi hücrede bir düğmeye basıldığını nasıl bulacağımı bilmiyorum. Şu anda gönderenin etiketini yalnızca düğmelerden birine basıldığında alıyorum. Bir düğmeye basıldığında hücre sıra numarasını da almanın bir yolu var mı?

Yanıtlar:


278

Bunun yerine gerçekten bu yöntemi kullanmalısınız:

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

Swift versiyonu:

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

Bu indexPath, basılan düğmenin konumuna göre size verecektir . Ardından cellForRowAtIndexPath, hücreye indexPath.rowihtiyacınız varsa veya satır numarasına ihtiyacınız varsa aramanız yeterlidir .

Paranoyak iseniz , tablo görünümünde o nokta için bulunamama if (indexPath) ...ihtimaline karşı kullanmadan önce kontrol edebilirsiniz indexPath.

Apple, görünüm yapısını değiştirmeye karar verirse, diğer tüm yanıtların bozulma olasılığı yüksektir.


8
bu, milyonlarca kez. diğerlerinin hiçbiri işe yaramadı, ancak bu mükemmeldi ve açık ara en basit çözüm
ine

2
Bu cevap işe yarıyor çünkü doğru çözüm. Diğerleri geçici çözümlerdir. Teşekkürler!
Bruno Philipe

1
Eğer durumda yok olması self.tableview , bu sayfadaki benim cevaba bakınız.
Ashok

1
Göndericimin yanlış sınıf olduğunu anladığımda bu benim için çalıştı. UIB düğmesine basılması için düzeltildi ve şimdi çalışıyor!
lordB8r

1
sadece yöntemin convertPoint:*to*Viewolmadığını unutmayın convertPoint:*from*View. Ben ... Xcode otomatik tamamlama kullanılan ve fromView yöntemi yalnızca çalışmıyor giden ile sona erdi
tGilani

40

Düzenleme: Bu cevap güncel değil. Lütfen bunun yerine bu yöntemi kullanın


Bunu dene:

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

Düzenleme: contentView kullanıyorsanız, bunun yerine buttonCell için bunu kullanın:

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

1
Alt görünümleri hücrenin kendisine değil, yalnızca contentViewözelliğine eklemeniz gerekiyor - bu nedenle bu çözüm gerçekten işe yaramıyor.

1
@ H2CO3 ile aynı fikirdeyim ve ayrıca bunun denetimlerden referans alınarak yapılması gerektiğini düşünmüyorum. Lütfen aşağıda daha iyi bir yol görün: stackoverflow.com/a/16270198/308315
iwasrobbed

@minimalpop, lütfen doğru cevabı değiştirir misiniz? daha iyi bir Soru / Cevap sahibi olmak için!
Thomas Besnehard

Bu, iOS 7'de çalışmaz. İndexPathForRowAtPoint'i kullanın: aşağıdaki yanıt
Austin

Aynı sürümü bir UICollectionView ile denedim ve mükemmel çalışıyor. Çok teşekkürler!
Claus

18

Herhangi bir özel alt görünümü olan hücrenin indexPath'ini getirmek için bu yolu öneririm - ( iOS 7 ve önceki tüm sürümlerle uyumlu )

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

Bu self.tablviewikisini de gerektirmez .

Ayrıca, özel alt görünümünüze UIGestureRecognizer'ın bir @selector'ı aracılığıyla eklenmesini istiyorsanız yararlı olan yorumlanmış koda dikkat edin.


Uitableviewcontroller'da bulunan verilere ihtiyacım olursa ne olacak?
iosMentalist

Güzel cevap Eğer bir arama çubuğunuz varsa ve şu anda hangi tablonun kullanıldığını öğrenmek istiyorsanız, bunu da kullanabilirsiniz.
Suraj K Thomas

tablo hücre hiyerarşisi değişti mi? Ne tür değişikliklerin olduğunu anlamama yardım edebilir misin ve bu daha fazla değişebilir mi?
Kamaldeep singh Bhatia

3

İki yol var:

  1. @ H2CO3 doğru. @ User523234'ün önerdiği şeyi yapabilirsiniz, ancak küçük bir değişiklikle, UIButton ve UITableViewCell arasında gelmesi gereken UITableViewCellContentView'a uymak için. Yani kodunu değiştirmek için:

    - (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. Özel bir UITableViewCell (kendi alt sınıfınız) oluşturursanız, selfIBAction'da basitçe çağırabilirsiniz . Hücreyi kurarken film şeridi kullanarak veya programlı olarak IBAction işlevini düğmenize bağlayabilirsiniz.

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

2

Hücreye düğmeler eklediğinizi varsayıyorum cellForRowAtIndexPath, sonra yapacağım şey özel bir sınıf alt sınıfı oluşturmak UIButton, adı verilen bir etiketrowNumber eklemek ve hücreye düğme eklerken bu verileri eklemek.


3
Bu iyi, ancak bunun için bir alt sınıf oluşturmak için bir neden yok UIButton. tagortak bir özelliğidir UIView.
Rob Napier

Ne düşündüğümü bilmiyorum ve UI bir şeyin bir UI olmadığını varsayıyorum , düzeltme için teşekkürler!
Derek Li

2

Başka bir basit yol:

  • Tablo görünümünde temas noktasını alın

  • Ardından noktadaki hücrenin dizin yolunu alın

  • Dizin yolu satır dizini içerir

Kod:

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

Hızlı 3

Not: Meta bu tür düzenlemelere karşı çıkması dışında, yukarıdaki kabul edilen yanıta gerçekten girmelidir .

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

İki küçük yorum:

  1. Varsayılan işlev, herhangi bir gönderici türüne sahiptir ve dönüştürme içermeyen işlevdir.
  2. CGPointZero, CGPoint () ile değiştirilebilir

Mükemmel çalışıyor.

0

Çözümlerden biri, düğmenin süpervizörünün etiketini veya hatta görünüm hiyerarşisinde daha yüksek olanı kontrol etmek olabilir (düğme hücrenin içerik görünümündeyse).


0

Kodu hızlı bir şekilde paylaşmak istiyorum -

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

Hızlı olarak:

@IBAction func buttonAction(_ sender: UIButton) {
    guard let indexPath = tableView.indexPathForRow(at: sender.convert(CGPoint(), to: tableView)) else {
        return
    }
    // do something
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.