it-swarm.com.de

Klicken Sie in UITableViewCell auf die Schaltfläche

Ich habe einen Ansichtscontroller mit einer Tabellenansicht und einer separaten Spitze für die Tabellenzellenvorlage. Die Zellenvorlage enthält einige Schaltflächen. Ich möchte auf den Schaltflächenklick zusammen mit dem Index der Zelle zugreifen, die in den View-Controller geklickt wurde, in dem ich die Tabellenansicht definiert habe.

Also habe ich ViewController.h und ViewController.m wo ich UITableView und TableTemplate.h, TableTemplate.m und TableTemplate.xib wo ich die Spitze definiert habe. Ich möchte, dass die Schaltfläche auf Ereignis mit Zellenindex in ViewController.m klickt.

Wie kann ich das machen?

122
ankit_rck

1) Weisen Sie in Ihrer cellForRowAtIndexPath:-Methode das Schaltflächen-Tag als Index zu:

cell.yourbutton.tag = indexPath.row;

2) Fügen Sie ein Ziel und eine Aktion für Ihre Schaltfläche hinzu:

[cell.yourbutton addTarget:self action:@selector(yourButtonClicked:) forControlEvents:UIControlEventTouchUpInside];

3) Code-Aktionen basierend auf dem Index in ViewControler:

-(void)yourButtonClicked:(UIButton*)sender
{
     if (sender.tag == 0) 
     {
         // Your code here
     }
}

Updates für mehrere Abschnitte:

Sie können diesen Link markieren, um das Klicken der Schaltflächen in der Tabellenansicht für mehrere Zeilen und Abschnitte zu erkennen.

245
Mani

Delegierte sind der Weg zu gehen.

Wie bei anderen Antworten zu sehen, könnten Ansichten mit Hilfe von Ansichten veraltet sein. Wer weiß, dass es morgen einen weiteren Wrapper gibt und möglicherweise cell superview]superview]superview]superview] verwenden muss. Und wenn Sie Tags verwenden, erhalten Sie n Anzahl if-Bedingungen, um die Zelle zu identifizieren. Um all das zu vermeiden, richten Sie Delegierte ein. (Dadurch erstellen Sie eine wiederverwendbare Zellklasse. Sie können dieselbe Zellklasse als Basisklasse verwenden, und Sie müssen lediglich die Delegat-Methoden implementieren.)

Zunächst benötigen wir eine Schnittstelle (Protokoll), über die Zelle die Klicks von Schaltern kommunizieren (delegieren) kann. (Sie können eine separate .h-Datei für das Protokoll erstellen und sowohl in den Table-View-Controller als auch in die benutzerdefinierten Zellklassen OR einfügen. Fügen Sie diese einfach in eine benutzerdefinierte Zellklasse ein, die trotzdem in den Table-View-Controller aufgenommen wird.)

@protocol CellDelegate <NSObject>
- (void)didClickOnCellAtIndex:(NSInteger)cellIndex withData:(id)data;
@end

Fügen Sie dieses Protokoll in einen benutzerdefinierten Zellen- und Tabellensicht-Controller ein. Stellen Sie sicher, dass der Table View Controller dieses Protokoll bestätigt. 

Erstellen Sie in der benutzerdefinierten Zelle zwei Eigenschaften:

@property (weak, nonatomic) id<CellDelegate>delegate;
@property (assign, nonatomic) NSInteger cellIndex;

Klicken Sie in UIButton IBAction-Delegat auf: (Dasselbe kann für jede Aktion in der benutzerdefinierten Zellklasse ausgeführt werden, die zurück an den Ansichtscontroller delegiert werden muss).

- (IBAction)buttonClicked:(UIButton *)sender {
    if (self.delegate && [self.delegate respondsToSelector:@selector(didClickOnCellAtIndex:withData:)]) {
        [self.delegate didClickOnCellAtIndex:_cellIndex withData:@"any other cell data/property"];
    }
}

Legen Sie im Table-View-Controller cellForRowAtIndexPath nach dem Entfernen der Zelle die obigen Eigenschaften fest.

cell.delegate = self;
cell.cellIndex = indexPath.row; // Set indexpath if its a grouped table.

Implementieren Sie den Delegaten in der Tabellensichtsteuerung:

- (void)didClickOnCellAtIndex:(NSInteger)cellIndex withData:(id)data
{
    // Do additional actions as required.
    NSLog(@"Cell at Index: %d clicked.\n Data received : %@", cellIndex, data);
}

Dies wäre der ideale Ansatz, um benutzerdefinierte Aktionen für Zellschaltflächen in der Tabellensichtsteuerung zu erhalten.

143
GoodSp33d

Anstatt mit Tags zu spielen, habe ich einen anderen Ansatz gewählt. Delegierte für meine Unterklasse von UITableViewCell (OptionButtonsCell) und fügte eine indexPath-Variable hinzu. Von meinem Button im Storyboard aus habe ich @IBAction mit der OptionButtonsCell verbunden und dort sende ich die Delegat-Methode mit dem richtigen indexPath an alle Interessierten. In der Zelle für den Indexpfad setze ich den aktuellen Indexpfad und es funktioniert :)

Lassen Sie den Code für sich sprechen:

Swift 3 Xcode 8

OptionButtonsTableViewCell.Swift

import UIKit
protocol OptionButtonsDelegate{
    func closeFriendsTapped(at index:IndexPath)
}
class OptionButtonsTableViewCell: UITableViewCell {
    var delegate:OptionButtonsDelegate!
    @IBOutlet weak var closeFriendsBtn: UIButton!
    var indexPath:IndexPath!
    @IBAction func closeFriendsAction(_ sender: UIButton) {
        self.delegate?.closeFriendsTapped(at: indexPath)
    }
}

MyTableViewController.Swift

class MyTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, OptionButtonsDelegate {...

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "optionCell") as! OptionButtonsTableViewCell
    cell.delegate = self
    cell.indexPath = indexPath
    return cell   
}

func closeFriendsTapped(at index: IndexPath) {
     print("button tapped at index:\(index)")
}
48
repoguy

Das sollte helfen: -

UITableViewCell* cell = (UITableViewCell*)[sender superview];
NSIndexPath* indexPath = [myTableView indexPathForCell:cell];

Hier ist sender die UIButton-Instanz, die das Ereignis sendet . myTableView ist die UITableView-Instanz, mit der Sie sich befassen.

Holen Sie sich einfach die Zellreferenz und die ganze Arbeit ist erledigt.

Möglicherweise müssen Sie die Schaltflächen aus contentView & .__ der Zelle entfernen und sie der UITableViewCell-Instanz direkt als Unteransicht hinzufügen.

Oder 

Sie können ein Tag-Benennungsschema für verschiedene UIButtons in cell.contentView ..__ formulieren. Mit diesem Tag können Sie später die Informationen zu Zeile und Abschnitt nach Bedarf kennen.

29
Tarun

Der folgende Code kann Ihnen helfen.

Ich habe UITableView mit der benutzerdefinierten Prototypzellenklasse UITableViewCell in UIViewController genommen.

Also habe ich ViewController.h, ViewController.m und TableViewCell.h, TableViewCell.m

Hier ist der Code dafür:

ViewController.h

@interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>

@property (strong, nonatomic) IBOutlet UITableView *tblView;

@end

ViewController.m

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return (YourNumberOfRows);
}

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

    static NSString *cellIdentifier = @"cell";

    __weak TableViewCell *cell = (TableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    if (indexPath.row==0) {
        [cell setDidTapButtonBlock:^(id sender)
         {
             // Your code here

         }];
    }    
    return cell;
}

Benutzerdefinierte Zellklasse:

TableViewCell.h

@interface TableViewCell : UITableViewCell

@property (copy, nonatomic) void (^didTapButtonBlock)(id sender);

@property (strong, nonatomic) IBOutlet UILabel *lblTitle;
@property (strong, nonatomic) IBOutlet UIButton *btnAction;

- (void)setDidTapButtonBlock:(void (^)(id sender))didTapButtonBlock;

@end

und 

UITableViewCell.m

@implementation TableViewCell

- (void)awakeFromNib {
    // Initialization code
    [self.btnAction addTarget:self action:@selector(didTapButton:) forControlEvents:UIControlEventTouchUpInside];

}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}
- (void)didTapButton:(id)sender {
    if (self.didTapButtonBlock)
    {
        self.didTapButtonBlock(sender);
    }
}

Hinweis : Hier habe ich alle UIControls mit Storyboard genommen.

Hoffe das kann dir helfen ... !!! 

20
Piyush Patel

Der Grund gefällt mir unter der Technik, weil er mir auch hilft, den Tabellenabschnitt zu identifizieren.

Schaltfläche in Zelle cellForRowAtIndexPath hinzufügen: 

 UIButton *selectTaskBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [selectTaskBtn setFrame:CGRectMake(15, 5, 30, 30.0)];
        [selectTaskBtn setTag:indexPath.section]; //Not required but may find useful if you need only section or row (indexpath.row) as suggested by MR.Tarun 
    [selectTaskBtn addTarget:self action:@selector(addTask:)   forControlEvents:UIControlEventTouchDown];
[cell addsubview: selectTaskBtn];

Event addTask:

-(void)addTask:(UIButton*)btn
{
    CGPoint buttonPosition = [btn convertPoint:CGPointZero toView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
    if (indexPath != nil)
    {
     int currentIndex = indexPath.row;
     int tableSection = indexPath.section;
    }
}

Hofft diese hilfe.

12
Yogesh Lolusare

Taruns Code funktioniert nicht unter iOS7, da sich die UITableViewCell-Struktur geändert hat und jetzt "UITableViewCellScrollView" angezeigt wird.

Dieser Beitrag Getting UITableViewCell mit Superview in iOS 7 bietet eine gute Lösung zum Erstellen einer Schleife, um die korrekte übergeordnete Ansicht zu finden, unabhängig von zukünftigen Änderungen in der Struktur. Es geht darum, eine Schleife zu erzeugen:

    UIView *superView = [sender superview];
    UIView *foundSuperView = nil;

    while (nil != superView && nil == foundSuperView) {
        if ([superView isKindOfClass:[UITableViewCell class]]) {
            foundSuperView = superView;
        } else {
            superView = superView.superview;
        }
    }

Der Link enthält Code für eine wiederverwendbare Lösung, dies sollte jedoch funktionieren.

6
Stenio Ferreira

Schnell 2.2

Sie müssen ein Ziel für diese Schaltfläche hinzufügen.

myButton.addTarget(self, action: #selector(ClassName.FunctionName(_:), forControlEvents: .TouchUpInside)

Funktionsname: verbunden // zum Beispiel

Und natürlich müssen Sie das Tag dieser Schaltfläche festlegen, da Sie es verwenden.

myButton.tag = indexPath.row

Sie können dies erreichen, indem Sie UITableViewCell subclassing. Verwenden Sie es im Interface Builder, lassen Sie einen Knopf auf diese Zelle fallen, verbinden Sie es über eine Steckdose und los geht's.

So rufen Sie das Tag in der verbundenen Funktion auf:

func connected(sender: UIButton) {
    let buttonTag = sender.tag
    // Do any additional setup
}
6
Himanshu padia

Swift 3 mit einem Verschluss

Eine Nice-Lösung verwendet eine Schließung in einer benutzerdefinierten UITableViewCell, um einen Rückruf an den viewController für eine Aktion auszuführen.

In der Zelle:

final class YourCustomCell: UITableViewCell {

    var callbackClosure: (() -> Void)?

    // Configure the cell here
    func configure(object: Object, callbackClosure: (() -> Void)?) {
       self.callbackClosure = callbackClosure
    }


// MARK: - IBAction
extension YourCustomCell {
    @IBAction fileprivate func actionPressed(_ sender: Any) {
        guard let closure = callbackClosure else { return }
        closure()
    }
}

In View Controller: Tableview Delegate

extension YourViewController: UITableViewDelegate {

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        guard let cell: YourCustomCell = cell as? YourCustomCell else { return }
        cell.configure(object: object, callbackClosure: { [weak self] in
            self?.buttonAction()
        })
     }
 }

fileprivate extension YourViewController {

    func buttonAction() {
        // do your actions here 
    }
}
5
Sevy11

Ich finde es am einfachsten, die Schaltfläche in Ihrer Zelle (Swift 3) zu subklassifizieren:

class MyCellInfoButton: UIButton {
    var indexPath: IndexPath?
}

In Ihrer Zellklasse:

class MyCell: UICollectionViewCell {
    @IBOutlet weak var infoButton: MyCellInfoButton!
   ...
}

Geben Sie in der Datenquelle der Tabellen- oder Sammlungsansicht oder der Sammlungsansicht der Zelle den Indexpfad der Schaltfläche an:

cell.infoButton.indexPath = indexPath

Sie können diesen Code also einfach in Ihren Table-View-Controller einfügen:

@IBAction func handleTapOnCellInfoButton(_ sender: MyCellInfoButton) {
        print(sender.indexPath!) // Do whatever you want with the index path!
}

Vergessen Sie nicht, die Klasse der Schaltfläche in Ihrem Interface Builder festzulegen und mit der Funktion handleTapOnCellInfoButton zu verknüpfen!


bearbeitet:

Abhängigkeitseinspritzung verwenden. So richten Sie den Abruf ein:

class MyCell: UICollectionViewCell {
    var someFunction: (() -> Void)?
    ...
    @IBAction func didTapInfoButton() {
        someFunction?()
    }
}

und fügen Sie den Abschluss in die willDisplay-Methode des Delegaten der Sammlungsansicht ein:

 func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    (cell as? MyCell)?.someFunction = {
        print(indexPath) // Do something with the indexPath.
    }
}
4
yesleon

Es ist für mich Arbeit.

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     UIButton *Btn_Play = (UIButton *)[cell viewWithTag:101];
     [Btn_Play addTarget:self action:@selector(ButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
}
-(void)ButtonClicked:(UIButton*)sender {
     CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.Tbl_Name];
     NSIndexPath *indexPath = [self.Tbl_Name indexPathForRowAtPoint:buttonPosition];
}
4
// Add action in cell for row at index path -tableView

cell.buttonName.addTarget(self, action: #selector(ViewController.btnAction(_:)), for: .touchUpInside)

// Button Action

  @objc func btnAction(_ sender: AnyObject) {



        var position: CGPoint = sender.convert(.zero, to: self.tableView)


        let indexPath = self.tableView.indexPathForRow(at: position)
        let cell: UITableViewCell = tableView.cellForRow(at: indexPath!)! as
        UITableViewCell




}
1
Hitesh Chauhan

Verwenden Sie Swift-Verschlüsse:

class TheCell: UITableViewCell {

    var tapCallback: (() -> Void)?

    @IBAction func didTap(_ sender: Any) {
        tapCallback?()
    }
}

extension TheController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: TheCell.identifier, for: indexPath) as! TheCell {
            cell.tapCallback = {
                //do stuff
            }
            return cell
    }
}
1
valexa

für Swift 4:

inside the cellForItemAt ,
   
cell.chekbx.addTarget(self, action: #selector(methodname), for: .touchUpInside)

then outside of cellForItemAt
@objc func methodname()
{
//your function code
}

0
Radhe Yadav

@Mani-Antwort ist gut, jedoch werden Tags mit Ansichten in cellIs contentView häufig für andere Zwecke verwendet. Sie können stattdessen das Tag der Zelle (oder das contentView-Tag der Zelle) verwenden:

1) Weisen Sie in Ihrer cellForRowAtIndexPath:-Methode das Tag der Zelle als Index zu:

cell.tag = indexPath.row; // or cell.contentView.tag...

2) Fügen Sie ein Ziel und eine Aktion für Ihre Schaltfläche hinzu:

[cell.yourbutton addTarget:self action:@selector(yourButtonClicked:) forControlEvents:UIControlEventTouchUpInside];

3) Erstellen Sie eine Methode, die die Zeile des Absenders zurückgibt (danke @Stenio Ferreira):

- (NSInteger)rowOfSender:(id)sender
{
    UIView *superView = sender.superview;
    while (superView) {
        if ([superView isKindOfClass:[UITableViewCell class]])
            break;
        else
            superView = superView.superview;
    }

    return superView.tag;
}

4) Code-Aktionen basierend auf dem Index:

-(void)yourButtonClicked:(UIButton*)sender
{
     NSInteger index = [self rowOfSender:sender];
     // Your code here
}
0
Borzh

CustomTableCell.h ist eine UITableViewCell:

@property (weak, nonatomic) IBOutlet UIButton *action1Button;
@property (weak, nonatomic) IBOutlet UIButton *action2Button;

MyVC.m nach dem Import:

@interface MYTapGestureRecognizer : UITapGestureRecognizer
@property (nonatomic) NSInteger dataint;
@end

Innerhalb von "cellForRowAtIndexPath" in MyVC.m:

//CustomTableCell 
CustomTableCell *cell = (CustomTableCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

//Set title buttons
[cell.action1Button setTitle:[NSString stringWithString:NSLocalizedString(@"action1", nil)] forState:UIControlStateNormal];
[cell.action2Button setTitle:[NSString stringWithString:NSLocalizedString(@"action2", nil)] forState:UIControlStateNormal];

//Set visibility buttons
[cell.action1Button setHidden:FALSE];
[cell.action2Button setHidden:FALSE];

//Do 1 action
[cell.action1Button addTarget:self action:@selector(do1Action :) forControlEvents:UIControlEventTouchUpInside];

//Do 2 action
MYTapGestureRecognizer *action2Tap = [[MYTapGestureRecognizer alloc] initWithTarget:self action:@selector(do2Action :)];
cancelTap.numberOfTapsRequired = 1;
cancelTap.dataint = indexPath.row;
[cell.action2Button setUserInteractionEnabled:YES];
[cell.action2Button addGestureRecognizer:action2Tap];

MyVC.m:

-(void)do1Action :(id)sender{
//do some action that is not necessary fr data
}

-(void)do2Action :(UITapGestureRecognizer *)tapRecognizer{
MYTapGestureRecognizer *tap = (MYTapGestureRecognizer *)tapRecognizer;
numberTag = tap.dataint;
FriendRequest *fr = [_list objectAtIndex:numberTag];

//connect with a WS o do some action with fr data

//actualize list in tableView
 [self.myTableView reloadData];
}
0
Mer