Wykrywanie, który UIButton został naciśnięty w widoku UITableView

Mam UITableView z 5 UITableViewCells. Każda komórka zawiera UIButton, który jest ustawiony w następujący sposób:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     NSString *identifier = @"identifier";
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
     if (cell == nil) {
         cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
         [cell autorelelase];

         UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 40, 20)];
         [button addTarget:self action:@selector(buttonPressedAction:) forControlEvents:UIControlEventTouchUpInside];
         [button setTag:1];
         [cell.contentView addSubview:button];

         [button release];
     }

     UIButton *button = (UIButton *)[cell viewWithTag:1];
     [button setTitle:@"Edit" forState:UIControlStateNormal];

     return cell;
}

Moje pytanie Jest Takie: w metodzie buttonPressedAction:, skąd mam wiedzieć, który przycisk został naciśnięty. Rozważałem użycie tagów, ale nie jestem pewien, czy jest to najlepsza trasa. Chciałbym móc jakoś przypisać indexPath do kontrolki.

- (void)buttonPressedAction:(id)sender
{
    UIButton *button = (UIButton *)sender;
    // how do I know which button sent this message?
    // processing button press for this row requires an indexPath. 
}

Jaki jest standardowy sposób na to?

Edit:

Rozwiązałem to, wykonując następujące czynności. Nadal chciałbym mieć opinia, czy jest to standardowy sposób, czy jest lepszy sposób?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     NSString *identifier = @"identifier";
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
     if (cell == nil) {
         cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
         [cell autorelelase];

         UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 40, 20)];
         [button addTarget:self action:@selector(buttonPressedAction:) forControlEvents:UIControlEventTouchUpInside];
         [cell.contentView addSubview:button];

         [button release];
     }

     UIButton *button = (UIButton *)[cell.contentView.subviews objectAtIndex:0];
     [button setTag:indexPath.row];
     [button setTitle:@"Edit" forState:UIControlStateNormal];

     return cell;
}

- (void)buttonPressedAction:(id)sender
{
    UIButton *button = (UIButton *)sender;
    int row = button.tag;
}

Ważne jest, aby pamiętać, że nie mogę ustawić tagu w tworzeniu komórki, ponieważ komórka może zostać usunięta. Czuję się bardzo brudny. Musi być lepszy sposób.

Author: Paras Joshi, 2009-11-26

26 answers

W próbce Apple ' a stosuje się następującą metodę:

[button addTarget:self action:@selector(checkButtonTapped:) forControlEvents:UIControlEventTouchUpInside];

Następnie w touch handler pobierana jest współrzędna dotykowa, a ścieżka indeksu jest obliczana z tej współrzędnej:

- (void)checkButtonTapped:(id)sender
{
    CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
    if (indexPath != nil)
    {
     ...
    }
}
 390
Author: Vladimir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-29 13:39:14

Odkryłem, że metoda wykorzystania superview ' s superview do uzyskania odniesienia do ścieżki indeksowej komórki działała idealnie. Dzięki iphonedevbook.com dla końcówki link text

-(void)buttonPressed:(id)sender {
 UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
 NSIndexPath *clickedButtonPath = [self.tableView indexPathForCell:clickedCell];
...

}
 48
Author: Cocoanut,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-06 02:54:37

Oto Jak to robię. Proste i zwięzłe:

- (IBAction)buttonTappedAction:(id)sender
{
    CGPoint buttonPosition = [sender convertPoint:CGPointZero
                                           toView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
    ...
 43
Author: Chris Schwerdt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-30 10:33:52

Znalazłem fajne rozwiązanie tego problemu gdzie indziej, bez bałaganu z tagami na przycisku:

- (void)buttonPressedAction:(id)sender {

NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition];

do stuff with the indexPath...
}
 6
Author: Alpinista,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-10 23:32:15

Jak o wysyłanie informacji jak {[1] } w UIButton za pomocą runtime injection.

1) potrzebujesz runtime przy imporcie

2) Dodaj stałą statyczną

3) dodaj NSIndexPath do przycisku w runtime używając:

(void) setMetaData: (id)target withObject: (id)newObj

4) po naciśnięciu przycisku Pobierz metadane za pomocą:

(id) metadane: (id)target

Enjoy

    #import <objc/runtime.h>
    static char const * const kMetaDic = "kMetaDic";


    #pragma mark - Getters / Setters

- (id)metaData:(id)target {
    return objc_getAssociatedObject(target, kMetaDic);
}

- (void)setMetaData:(id)target withObject:(id)newObj {
    objc_setAssociatedObject(target, kMetaDic, newObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}



    #On the cell constructor
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    ....
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    ....
    [btnSocial addTarget:self
                                   action:@selector(openComments:)
                         forControlEvents:UIControlEventTouchUpInside];

    #add the indexpath here or another object
    [self setMetaData:btnSocial withObject:indexPath];

    ....
    }



    #The action after button been press:

    - (IBAction)openComments:(UIButton*)sender{

        NSIndexPath *indexPath = [self metaData:sender];
        NSLog(@"indexPath: %d", indexPath.row);

        //Reuse your indexpath Now
    }
 5
Author: magno cardona,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-01 05:00:30
func buttonAction(sender:UIButton!)
    {
        var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tablevw)
       let indexPath = self.tablevw.indexPathForRowAtPoint(position)
       let cell: TableViewCell = tablevw.cellForRowAtIndexPath(indexPath!) as TableViewCell
        println(indexPath?.row)
        println("Button tapped")
    }
 5
Author: Ankit Bansal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-31 05:58:11

To do (@Vladimir)'s answer is Swift:

var buttonPosition = sender.convertPoint(CGPointZero, toView: self.tableView)
var indexPath = self.tableView.indexPathForRowAtPoint(buttonPosition)!
/ Align = "center" bgcolor = "# e0ffe0 " / cesarz chin / / align = center / .."NSIndexPath nie jest podtypem NSString"
 5
Author: dennis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-24 16:27:59

Użyłbym właściwości tag, tak jak powiedziałeś, ustawiając tag w ten sposób:

[button setTag:indexPath.row];

Następnie uzyskanie znacznika wewnątrz buttonPressedAction tak:

((UIButton *)sender).tag

Lub

UIButton *button = (UIButton *)sender; 
button.tag;
 3
Author: ACBurk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-26 10:16:38

Chociaż podoba mi się sposób tagowania... jeśli nie chcesz używać tagów z jakiegokolwiek powodu, możesz utworzyć member NSArray premade buttons:

NSArray* buttons ;

Następnie utwórz te przyciski przed renderowaniem widoku tableView i wciśnij je do tablicy.

Następnie wewnątrz funkcji tableView:cellForRowAtIndexPath: możesz wykonać:

UIButton* button = [buttons objectAtIndex:[indexPath row] ] ;
[cell.contentView addSubview:button];

Następnie w funkcji buttonPressedAction: można wykonać

- (void)buttonPressedAction:(id)sender {
   UIButton* button = (UIButton*)sender ;
   int row = [buttons indexOfObject:button] ;
   // Do magic
}
 3
Author: Eld,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-01 05:00:59

Do obsługi sekcji-zapisałem NSIndexPath w niestandardowym UITableViewCell

W CLKIndexPricesHEADERTableViewCell.xib

IN Ib Add UIButton to XIB-DONT add action!

Add outlet @property (retain, nonatomic) Iboutlet UIButton *buttonIndexSectionClose;

Nie CTRL + przeciągaj akcji w IB (wykonanej w kodzie poniżej)

@interface CLKIndexPricesHEADERTableViewCell : UITableViewCell
...
@property (retain, nonatomic) IBOutlet UIButton *buttonIndexSectionClose;
@property (nonatomic, retain) NSIndexPath * indexPathForCell;
@end

In viewForHeaderInSection (powinno działać również dla cellForRow.... etc jeśli tabela ma tylko 1 sekcję)

- viewForHeaderInSection is called for each section 1...2...3
- get the cell CLKIndexPricesHEADERTableViewCell 
- getTableRowHEADER just does the normal dequeueReusableCellWithIdentifier
- STORE the indexPath IN the UITableView cell
- indexPath.section = (NSInteger)section
- indexPath.row = 0 always (we are only interested in sections)

- (UIView *) tableView:(UITableView *)tableView1 viewForHeaderInSection:(NSInteger)section {


    //Standard method for getting a UITableViewCell
    CLKIndexPricesHEADERTableViewCell * cellHEADER = [self getTableRowHEADER];

...użyj sekcja pobierania danych dla komórki

...fill it in

   indexName        = ffaIndex.routeCode;
   indexPrice       = ffaIndex.indexValue;

   //

   [cellHEADER.buttonIndexSectionClose addTarget:self
                                          action:@selector(buttonDELETEINDEXPressedAction:forEvent:)
                                forControlEvents:UIControlEventTouchUpInside];


   cellHEADER.indexPathForCell = [NSIndexPath indexPathForRow:0 inSection:section];


    return cellHEADER;
}

Użytkownik naciska przycisk DELETE na nagłówku sekcji i wywoła

- (void)buttonDELETEINDEXPressedAction:(id)sender forEvent:(UIEvent *)event
{
    NSLog(@"%s", __PRETTY_FUNCTION__);


    UIView *  parent1 = [sender superview];   // UiTableViewCellContentView
    //UIView *myContentView = (UIView *)parent1;

    UIView *  parent2 = [parent1 superview];  // custom cell containing the content view
    //UIView *  parent3 = [parent2 superview];  // UITableView containing the cell
    //UIView *  parent4 = [parent3 superview];  // UIView containing the table


    if([parent2 isMemberOfClass:[CLKIndexPricesHEADERTableViewCell class]]){
        CLKIndexPricesHEADERTableViewCell *myTableCell = (CLKIndexPricesHEADERTableViewCell *)parent2;

        //UITableView *myTable = (UITableView *)parent3;
        //UIView *mainView = (UIView *)parent4;

        NSLog(@"%s indexPath.section,row[%d,%d]", __PRETTY_FUNCTION__, myTableCell.indexPathForCell.section,myTableCell.indexPathForCell.row);

        NSString *key = [self.sortedKeysArray objectAtIndex:myTableCell.indexPathForCell.section];
        if(key){
            NSLog(@"%s DELETE object at key:%@", __PRETTY_FUNCTION__,key);
            self.keyForSectionIndexToDelete = key;
            self.sectionIndexToDelete = myTableCell.indexPathForCell.section;

            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Remove Index"
                                                                message:@"Are you sure"
                                                               delegate:self
                                                      cancelButtonTitle:@"No"
                                                      otherButtonTitles:@"Yes", nil];
            alertView.tag = kALERTVIEW_REMOVE_ONE_INDEX;
            [alertView show];
            [alertView release];
            //------
        }else{
            NSLog(@"ERROR: [%s] key is nil for section:%d", __PRETTY_FUNCTION__,myTableCell.indexPathForCell.section);
        }

    }else{
        NSLog(@"ERROR: [%s] CLKIndexPricesHEADERTableViewCell not found", __PRETTY_FUNCTION__);
    }
}

W tym przykładzie dodałem przycisk Usuń, więc powinien pokazać UIAlertView, aby to potwierdzić

Zapisuję sekcję i klucz do słownika przechowując informacje o sekcji w ivar w VC

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
   if(alertView.tag == kALERTVIEW_REMOVE_ONE_INDEX){
        if(buttonIndex==0){
            //NO
            NSLog(@"[%s] BUTTON:%d", __PRETTY_FUNCTION__,buttonIndex);
            //do nothing
        }
        else if(buttonIndex==1){
            //YES
            NSLog(@"[%s] BUTTON:%d", __PRETTY_FUNCTION__,buttonIndex);
            if(self.keyForSectionIndexToDelete != nil){

                //Remove the section by key
                [self.indexPricesDictionary removeObjectForKey:self.keyForSectionIndexToDelete];

                //sort the keys so sections appear alphabetically/numbericsearch (minus the one we just removed)
                [self updateTheSortedKeysArray];                

                //Delete the section from the table using animation
                [self.tableView beginUpdates];

                [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:self.sectionIndexToDelete]
                              withRowAnimation:UITableViewRowAnimationAutomatic];
                [self.tableView endUpdates];

                //required to trigger refresh of myTableCell.indexPathForCell else old values in UITableViewCells
                [self.tableView reloadData];
            }else{
                NSLog(@"ERROR: [%s] OBJECT is nil", __PRETTY_FUNCTION__);
            }
        }
        else {
            NSLog(@"ERROR: [%s] UNHANDLED BUTTON:%d", __PRETTY_FUNCTION__,buttonIndex);
        }
    }else {
        NSLog(@"ERROR: [%s] unhandled ALERTVIEW TAG:%d", __PRETTY_FUNCTION__,alertView.tag);
    }
}
 2
Author: brian.clear,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-11 14:58:41
A better way would be to subclass your button and add a indexPath property to it.

//Implement a subclass for UIButton.

@interface NewButton:UIButton
@property(nonatomic, strong) NSIndexPath *indexPath;


Make your button of type NewButton in the XIB or in the code whereever you are initializing them.

Then in the cellForRowAtIndexPath put the following line of code.

button.indexPath = indexPath;

return cell; //As usual



Now in your IBAction

-(IBAction)buttonClicked:(id)sender{
   NewButton *button = (NewButton *)sender;

//Now access the indexPath by buttons property..

   NSIndexPath *indexPath = button.indexPath; //:)
}
 2
Author: mmmanishs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-19 08:06:31

To działa dla mnie równie dobrze, dzięki @ Cocoanut

Odkryłem, że metoda wykorzystania superview ' s superview do uzyskania odniesienia do ścieżki indeksowej komórki działała idealnie. Dzięki iphonedevbook.com (macnsmith) for the tip link text

-(void)buttonPressed:(id)sender {
 UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
 NSIndexPath *clickedButtonPath = [self.tableView indexPathForCell:clickedCell];
...

}
 1
Author: user366584,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-07 12:11:17

Możesz użyć wzoru znacznika:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     NSString *identifier = @"identifier";
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
     if (cell == nil) {
         cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
         [cell autorelelase];

         UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 40, 20)];
         [button addTarget:self action:@selector(buttonPressedAction:) forControlEvents:UIControlEventTouchUpInside];
         [button setTag:[indexPath row]]; //use the row as the current tag
         [cell.contentView addSubview:button];

         [button release];
     }

     UIButton *button = (UIButton *)[cell viewWithTag:[indexPath row]]; //use [indexPath row]
     [button setTitle:@"Edit" forState:UIControlStateNormal];

     return cell;
}

- (void)buttonPressedAction:(id)sender
{
    UIButton *button = (UIButton *)sender;
    //button.tag has the row number (you can convert it to indexPath)
}
 0
Author: Nir Levy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-26 10:16:46

Czy coś przeoczyłem? Nie możesz użyć nadawcy do identyfikacji przycisku. Nadawca poda ci takie informacje:

<UIButton: 0x4b95c10; frame = (246 26; 30 30); opaque = NO; tag = 104; layer = <CALayer: 0x4b95be0>>

Następnie, jeśli chcesz zmienić właściwości przycisku, powiedz obraz tła, po prostu powiedz nadawcy:

[sender setBackgroundImage:[UIImage imageNamed:@"new-image.png"] forState:UIControlStateNormal];

Jeśli potrzebujesz tagu, metoda Acburka jest w porządku.

 0
Author: Michael Morrison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-22 22:48:41
// how do I know which button sent this message?
// processing button press for this row requires an indexPath.

Całkiem proste:

- (void)buttonPressedAction:(id)sender
{
    UIButton *button = (UIButton *)sender;
    CGPoint rowButtonCenterInTableView = [[rowButton superview] convertPoint:rowButton.center toView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:rowButtonCenterInTableView];
    MyTableViewItem *rowItem = [self.itemsArray objectAtIndex:indexPath.row];
    // Now you're good to go.. do what the intention of the button is, but with
    // the context of the "row item" that the button belongs to
    [self performFooWithItem:rowItem];
}

Działa dobrze dla mnie: P

Jeśli chcesz dostosować ustawienia działania docelowego, możesz dołączyć parametr zdarzenia do metody, a następnie użyć dotknięć tego zdarzenia, aby rozwiązać współrzędne dotknięcia. Współrzędne nadal muszą być rozwiązane w granicach widoku dotykowego, ale może to wydawać się łatwiejsze dla niektórych osób.

 0
Author: ohhorob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-14 02:24:02

Utwórz tablicę nsmutable i umieść przycisk all w tej tablicy usint [array addObject:yourButton];

W metodzie naciśnięcia przycisku

-

 (void)buttonPressedAction:(id)sender
{
    UIButton *button = (UIButton *)sender;

for(int i=0;i<[yourArray count];i++){

if([buton isEqual:[yourArray objectAtIndex:i]]){

//here write wat u need to do

}
}
 0
Author: rajesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-07 10:02:52

Mała odmiana odpowiedzi Cocoanuts (która pomogła mi rozwiązać ten problem), gdy przycisk znajdował się w stopce tabeli (co uniemożliwia znalezienie 'klikniętej komórki':

-(IBAction) buttonAction:(id)sender;
{
    id parent1 = [sender superview];   // UiTableViewCellContentView
    id parent2 = [parent1 superview];  // custom cell containing the content view
    id parent3 = [parent2 superview];  // UITableView containing the cell
    id parent4 = [parent3 superview];  // UIView containing the table

    UIView *myContentView = (UIView *)parent1;
    UITableViewCell *myTableCell = (UITableViewCell *)parent2;
    UITableView *myTable = (UITableView *)parent3;
    UIView *mainView = (UIView *)parent4;

    CGRect footerViewRect = myTableCell.frame;
    CGRect rect3 = [myTable convertRect:footerViewRect toView:mainView];    

    [cc doSomethingOnScreenAtY:rect3.origin.y];
}
 0
Author: software evolved,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-09 16:53:42

Zawsze używam tagów.

Musisz podklasować UITableviewCell i obsługiwać naciśnięcie przycisku stamtąd.

 0
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-01 05:01:31

To proste; zrób niestandardową komórkę i weź wylot przycisku

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
         NSString *identifier = @"identifier";
        customCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];

    cell.yourButton.tag = indexPath.Row;

- (void)buttonPressedAction:(id)sender

Zmień id w powyższej metodzie na (UIButton *)

Możesz uzyskać wartość tego, który przycisk jest stukany, wykonując nadawcę.tag.

 0
Author: piyush Bageria,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-01 05:02:10

Podklasuj przycisk do przechowywania wymaganej wartości, może Utwórz protokół (ControlWithData lub coś takiego). Ustaw wartość po dodaniu przycisku do komórki widoku tabeli. W zdarzeniu touch up sprawdź, czy nadawca przestrzega protokołu i wyodrębnij dane. Zwykle przechowuję odniesienie do rzeczywistego obiektu, który jest renderowany w komórce widoku tabeli.

 0
Author: Jerome Chan Yeow Heong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-06 02:59:31

SWIFT 2 UPDATE

Oto jak dowiedzieć się, który przycisk został naciśnięty + wyślij dane do innego Viewcontrollera z tego przycisku indexPath.row jak zakładam, że to jest punkt dla większości!

@IBAction func yourButton(sender: AnyObject) {


     var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
        let indexPath = self.tableView.indexPathForRowAtPoint(position)
        let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath!)! as
        UITableViewCell
        print(indexPath?.row)
        print("Tap tap tap tap")

    }

Dla tych, którzy używają klasy ViewController i dodali tableView, używam ViewController zamiast TableViewController, więc ręcznie dodałem tableView, aby uzyskać do niej dostęp.

Oto kod do przekazywania danych do innego VC po naciśnięciu tego przycisku i przejściu komórka indexPath.row

@IBAction func moreInfo(sender: AnyObject) {

    let yourOtherVC = self.storyboard!.instantiateViewControllerWithIdentifier("yourOtherVC") as! YourOtherVCVIewController



    var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
    let indexPath = self.tableView.indexPathForRowAtPoint(position)
    let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath!)! as
    UITableViewCell
    print(indexPath?.row)
    print("Button tapped")


    yourOtherVC.yourVarName = [self.otherVCVariable[indexPath!.row]]

    self.presentViewController(yourNewVC, animated: true, completion: nil)

}
 0
Author: lukaivicev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-07 10:21:55

Uwaga tutaj używam niestandardowej komórki ten kod działa dla mnie doskonale

 @IBAction func call(sender: UIButton)
    {
        var contentView = sender.superview;
        var cell = contentView?.superview as EmployeeListCustomCell
        if (!(cell.isKindOfClass(EmployeeListCustomCell)))
        {
            cell = (contentView?.superview)?.superview as EmployeeListCustomCell
        }

        let phone = cell.lblDescriptionText.text!
        //let phone = detailObject!.mobile!
        let url:NSURL = NSURL(string:"tel://"+phone)!;
        UIApplication.sharedApplication().openURL(url);
    }
 0
Author: Gaurav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-18 19:36:01

Rozwiązanie Chrisa Schwerdta, ale potem w Swifcie zadziałało dla mnie:

@IBAction func rateButtonTapped(sender: UIButton) {
    let buttonPosition : CGPoint = sender.convertPoint(CGPointZero, toView: self.ratingTableView)
    let indexPath : NSIndexPath = self.ratingTableView.indexPathForRowAtPoint(buttonPosition)!

    print(sender.tag)
    print(indexPath.row)
}
 0
Author: Rutger Huijsmans,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-17 12:10:18

Ten problem składa się z dwóch części:

1) uzyskanie ścieżki indeksu UITableViewCell, która zawiera wciśnięty UIButton

Są takie propozycje jak:

  • Aktualizacja UIButton'S tag w metodzie cellForRowAtIndexPath: z wykorzystaniem wartości row ścieżki indeksu. Nie jest to dobre rozwiązanie, ponieważ wymaga ciągłej aktualizacji tag i nie działa z widokami tabeli z więcej niż jedną sekcją.

  • Dodawanie właściwości NSIndexPath do niestandardowej komórki i aktualizowanie jej zamiast UIButton'S tag w metodzie cellForRowAtIndexPath:. Rozwiązuje to problem z wieloma sekcjami, ale nadal nie jest dobry, ponieważ wymaga aktualizacji zawsze.

  • Zachowując słabą refencję do rodzica UITableView w komórce niestandardowej podczas jej tworzenia i używając metody indexPathForCell:, aby uzyskać ścieżkę indeksu. Wydaje się trochę lepiej, nie ma potrzeby aktualizowania czegokolwiek w metodzie cellForRowAtIndexPath:, ale nadal wymaga ustawienia słabego odniesienia podczas tworzenia niestandardowej komórki.

  • Korzystanie z właściwości superView komórki, aby uzyskać odniesienie do rodzica UITableView. Nie ma potrzeby dodawania żadnych właściwości do niestandardowej komórki i nie ma potrzeby ustawiania / aktualizowania czegokolwiek podczas tworzenia/później. Ale cell ' s superView zależy od szczegółów implementacji iOS. Więc nie można go używać bezpośrednio.

Ale można to osiągnąć za pomocą prostej pętli, ponieważ jesteśmy pewni, że dana komórka musi być w widoku UITableView:

UIView* view = self;
while (view && ![view isKindOfClass:UITableView.class])
    view = view.superview;
UITableView* parentTableView = (UITableView*)view;

Więc te sugestie mogą być połączone w prostą i bezpieczną metodę niestandardowych komórek do uzyskania ścieżki indeksu:

- (NSIndexPath *)indexPath
{
    UIView* view = self;

    while (view && ![view isKindOfClass:UITableView.class])
        view = view.superview;

    return [(UITableView*)view indexPathForCell:self];
}

Od teraz, ta metoda może być użyta do wykrycia, które {[3] } jest naciśnięte.

2) informowanie innych stron o zdarzeniu naciśnij przycisk

Po wewnętrznej informacji, która UIButton jest wciśnięta w której komórce z dokładną ścieżką indeksu, informacja ta musi zostać wysłana do innych stron(najprawdopodobniej kontroler widoku obsługujący UITableView). Tak więc to zdarzenie kliknięcia przycisku może być obsługiwane na podobnym poziomie abstrakcji i logiki jak metoda didSelectRowAtIndexPath: delegata UITableView.

Dwa można w tym celu zastosować podejścia:

A) delegacja: komórka niestandardowa może mieć właściwość delegate i może definiować protokół. Po naciśnięciu przycisku po prostu wykonuje metody delegata na swojej właściwości delegate. Ale ta właściwość delegate musi być ustawiona dla każdej komórki niestandardowej podczas ich tworzenia. Jako alternatywę, komórka niestandardowa może również wykonywać swoje metody delegowania w widoku tabeli nadrzędnej delegate.

B) Centrum powiadomień: własne komórki mogą definiować niestandardowa nazwa powiadomienia i zamieść to powiadomienie ze ścieżką indeksu i informacjami widoku tabeli nadrzędnej dostępnymi w obiekcie userInfo. Nie trzeba niczego ustawiać dla każdej komórki, wystarczy dodać obserwatora dla powiadomienia niestandardowej komórki.

 0
Author: erkanyildiz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-27 05:19:55

Używam rozwiązania, które podklasa UIButton i pomyślałem, że powinienem podzielić się nim tutaj, kody w Swift:

class ButtonWithIndexPath : UIButton {
    var indexPath:IndexPath?
}

Następnie pamiętaj, aby zaktualizować to indexPath w cellForRow(at:)

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let returnCell = tableView.dequeueReusableCell(withIdentifier: "cellWithButton", for: indexPath) as! cellWithButton
    ...
    returnCell.button.indexPath = IndexPath
    returnCell.button.addTarget(self, action:#selector(cellButtonPressed(_:)), for: .touchUpInside)

    return returnCell
}

Więc odpowiadając na zdarzenie przycisku możesz go używać tak jak

func cellButtonPressed(_ sender:UIButton) {
    if sender is ButtonWithIndexPath {
        let button = sender as! ButtonWithIndexPath
        print(button.indexPath)
    }
}
 0
Author: Ben Ong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-24 10:21:30

Z Swift 4.2 i iOS 12, UITableView posiada metodę o nazwie indexPathForRow(at:). indexPathForRow(at:) ma następującą deklarację:

func indexPathForRow(at point: CGPoint) -> IndexPath?

Zwraca ścieżkę indeksu identyfikującą wiersz i sekcję w podanym punkcie.


Poniższy kompletny kod pokazuje, jak zaimplementować indexPathForRow(at:), Aby uzyskać odpowiednie IndexPath z UIButton znajdującego się w UITableViewCell:

import UIKit

class CustomCell: UITableViewCell {

    let button = UIButton(type: .system)

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        button.setTitle("Tap", for: .normal)
        contentView.addSubview(button)

        button.translatesAutoresizingMaskIntoConstraints = false
        button.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
        button.topAnchor.constraintEqualToSystemSpacingBelow(contentView.topAnchor, multiplier: 1).isActive = true
        button.leadingAnchor.constraintGreaterThanOrEqualToSystemSpacingAfter(contentView.leadingAnchor, multiplier: 1).isActive = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}
import UIKit

class TableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(CustomCell.self, forCellReuseIdentifier: "Cell")
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
        cell.button.addTarget(self, action: #selector(printIndexPath), for: .touchUpInside)
        return cell
    }

    @objc func printIndexPath(_ sender: UIButton) {
        let point = sender.convert(CGPoint.zero, to: tableView)
        guard let indexPath = tableView.indexPathForRow(at: point) else { return }
        print(indexPath)
    }

}
 0
Author: Imanou Petit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-07 21:46:33